# https://github.com/vishalsachdev/canvas-mcp Project Manual

Generated at: 2026-07-05 04:06:24 UTC

## Table of Contents

- [Overview](#page-overview)
- [Lib](#page-cli-lib)
- [Cli](#page-cli)
- [Core](#page-src-canvas_mcp-core)

<a id='page-overview'></a>

## Overview

### Related Pages

Related topics: [Lib](#page-cli-lib)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/vishalsachdev/canvas-mcp/blob/main/README.md)
- [cli/README.md](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/README.md)
- [cli/package.json](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/package.json)
- [config/overlays/README.md](https://github.com/vishalsachdev/canvas-mcp/blob/main/config/overlays/README.md)
- [internal/README.md](https://github.com/vishalsachdev/canvas-mcp/blob/main/internal/README.md)
- [package.json](https://github.com/vishalsachdev/canvas-mcp/blob/main/package.json)
- [pyproject.toml](https://github.com/vishalsachdev/canvas-mcp/blob/main/pyproject.toml)
- [src/canvas_mcp/core/config.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/config.py)
- [src/canvas_mcp/tools/rubrics.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/tools/rubrics.py)
- [src/canvas_mcp/server.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/server.py)
</details>

# Overview

`canvas-mcp` is a Model Context Protocol (MCP) server that bridges Canvas LMS and LLM clients such as Claude Desktop. It exposes Canvas REST endpoints as discrete MCP tools, letting a learning designer or instructor inspect, edit, and automate course content through natural-language conversations. The project is published at `https://github.com/vishalsachdev/canvas-mcp` and is maintained alongside a hosted Azure deployment and a Claude Desktop Extension distribution.

## Purpose and Scope

The server's purpose is to give an LLM structured, well-typed access to Canvas without forcing the model to hand-craft REST calls. Every Canvas concept a teacher touches — courses, modules, assignments, pages, discussions, rubrics, enrollments, syllabi — is wrapped in a tool function whose docstring describes its parameters and side effects.

The scope is intentionally Canvas-only. Authentication, base URL handling, and rate-limit retries live in `src/canvas_mcp/core/config.py`, while individual tool families live under `src/canvas_mcp/tools/`. The server is single-tenant per process: as of v1.4.0 it enforces one `CANVAS_API_URL` per instance to prevent SSRF (`Source: [src/canvas_mcp/core/config.py:1-120]()`). The configuration layer warns when `CANVAS_API_URL` is not normalized to the canonical `/api/v1` suffix, and issue #147 tracks promoting that warning to an automatic fix (`Source: [src/canvas_mcp/core/config.py:40-80]()`).

## Architecture and Runtime

`canvas-mcp` is a Python application built on FastMCP 2.x. The migration from the legacy MCP SDK was completed in v1.5.0 (see issue #145) and the dependency pin in `pyproject.toml` currently constrains `mcp>=1.26.0,<2` (`Source: [pyproject.toml:29]()`), with issue #142 tracking the eventual upgrade to MCP SDK v2 once stable ships.

At runtime the server speaks MCP over stdio for local clients and over an HTTP transport for hosted deployments. The TypeScript `cli/` directory produces a companion CLI used by the hosted flow to mint tokens, generate `mcp-remote` configurations, and run external-action approval. The CLI's `package.json` declares the Node entry points consumed by the Azure App Service container (`Source: [cli/package.json:1-40]()`).

The deployment story is split across two layers:

- **Kustomize overlays** under `config/overlays/` parameterize per-environment Azure manifests; the README enumerates the available overlays and how to combine them (`Source: [config/overlays/README.md:1-60]()`).
- **Internal hosting docs** under `internal/` cover the Entra-registered app, the `offline_access` scope, and the custom domain `canvas-mcp.disruptionlab.illinois.edu`. Issue #146 tracks requesting the `offline_access` scope so that `mcp-remote` clients stop re-logging in hourly (`Source: [internal/README.md:1-120]()`).

## Tool Surface

Tools are grouped by Canvas domain. The most-used families, with representative tools, are:

| Domain | Representative Tools | Notes |
|---|---|---|
| Courses & structure | `get_course_structure`, module helpers | Added in v1.1.0; returns module→items tree with summary stats (`Source: [src/canvas_mcp/server.py:1-200]()`) |
| Assignments | `update_assignment`, `get_my_upcoming_assignments` | Update path has long existed; user-scoped tools got an event-loop fix in v1.3.0 |
| Pages | `edit_page_content`, `delete_page` | `delete_page` carries a title-match safety check introduced in v1.1.0 |
| Discussions | `create_discussion_topic`, `update_discussion_topic` | `update_discussion_topic` closed the gap reported in issue #154 with v1.5.0 |
| Rubrics | `create_rubric`, `create_rubric_from_csv` | CSV variant added per issue #119; the legacy `create_rubric` is enabled via bracket-notation form-data in `rubrics.py` (`Source: [src/canvas_mcp/tools/rubrics.py:840-870]()`) |
| User-scoped | `get_my_todo_items`, `check_enrollment` | `check_enrollment` shipped in v1.4.0 |

Each tool follows the same conventions: validate the `course_id` argument, fetch or mutate through the Canvas client, and return a JSON-serializable summary that the LLM can reason about. Agent skills such as `canvas-course-qc` and `canvas-accessibility-auditor` (added in v1.1.0) sit on top of these tools to drive higher-level workflows like quality checks and accessibility audits.

## Distribution and Release Cadence

The project ships through three channels. The Python wheel is published to PyPI and consumed by local `uvx`/`pip` installs documented in `README.md` (`Source: [README.md:1-120]()`). The Claude Desktop Extension is packaged as a `.mcpb` archive; the scaffolding and release workflow for this artifact landed in v1.4.0 (`Source: [package.json:1-60]()`). Finally, the hosted Entra-authenticated deployment is documented under `internal/` and rolled out via the Kustomize overlays.

Releases follow a roughly monthly cadence. The most recent tag, v1.5.0, bundles `get_syllabus`, `create_rubric_from_csv`, `update_discussion_topic`, the FastMCP 2.x migration, and a security-hardening pass. Earlier milestones worth noting are v1.4.0 (SSRF tightening, Desktop Extension, Entra hosting), v1.3.0 (`create_rubric` and the event-loop fix for user-scoped tools, #99), v1.2.0 (role-based filtering and accessibility hardening), v1.1.0 (Learning Designer tools and skills), and v1.0.8 (ruff-enforced linting and release-workflow hardening). Weekly maintenance reports — for example #116 — sweep dependency, security, and CI areas and feed directly into the next release.

---

<a id='page-cli-lib'></a>

## Lib

### Related Pages

Related topics: [Overview](#page-overview), [Cli](#page-cli)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [cli/lib/clients.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/clients.js)
- [cli/lib/config-writer.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/config-writer.js)
- [cli/lib/wizard.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/wizard.js)
- [cli/lib/auth.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/auth.js)
- [cli/lib/hosted.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/hosted.js)
- [cli/lib/detect.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/detect.js)
</details>

# Lib

The `cli/lib/` directory is the shared JavaScript module layer powering the Canvas MCP command-line installer (`canvas-mcp-cli`). These modules wrap interactive prompts, client configuration generation, and host detection so the top-level CLI entry point can focus on orchestration rather than re-implementing per-client logic.

## Scope and Role

The `Lib` layer sits between the CLI dispatcher and external integrations. It exposes pure-ish helpers that:

- Detect which MCP-capable client (Claude Desktop, Cursor, VS Code Continue, etc.) is installed locally and where its configuration file lives.
- Walk users through setup questions (`wizard.js`).
- Persist the resulting settings (`config-writer.js`).
- Translate the host's preferred config schema into the canonical Canvas MCP connection (`clients.js`).
- Manage Entra ID / OAuth handshake details for the hosted Azure variant (`auth.js`, `hosted.js`).

Source: [cli/lib/detect.js]() is typically the entry helper for locating installed clients, while [cli/lib/clients.js]() holds the per-client serializer for the final JSON or TOML output.

## Core Modules

### Client Detection and Configuration

`detect.js` scans well-known install paths (Claude Desktop's `claude_desktop_config.json`, Cursor's `~/.cursor/mcp.json`, VS Code's workspace `.vscode/mcp.json`, etc.) and returns a normalized descriptor: `{ clientId, configPath, exists, writable }`. The wizard consumes this to decide whether to create, merge, or patch the host file.

`config-writer.js` performs the actual write. It is responsible for safely merging the Canvas MCP entry into the host's existing JSON (or TOML) without clobbering unrelated entries. It also handles atomic writes — temp file plus rename — to avoid leaving a half-written config that would brick the host application. Source: [cli/lib/config-writer.js]().

`clients.js` encodes the per-client shape: command name, argument template, env-var conventions, and whether the client expects stdio or HTTP transport. For example, Claude Desktop uses a `mcpServers` map keyed by server name, while VS Code Continue uses a `mcpServers` array under a different parent. Source: [cli/lib/clients.js]().

### Interactive Wizard

`wizard.js` exposes a function (commonly `runWizard()`) that drives an inquirer/prompts session collecting:

1. Canvas base URL (validated against SSRF — see issue #144, where multi-host support was intentionally removed in v1.4.0).
2. API token (or selection of Entra-hosted mode).
3. Target MCP client (multi-select, defaulting to all detected).
4. Optional scope: course IDs, user-scoped tools, etc.

The wizard then calls into `config-writer.js` for each selected client. Source: [cli/lib/wizard.js]().

### Hosted (Entra ID) Path

For the Azure-hosted variant, `hosted.js` collects the Entra app registration metadata (`client_id`, `tenant_id`, `redirect_uri`) and constructs the `mcp-remote` command line that downstream clients invoke. Issue #146 documents the related concern: the generated scope string must include `offline_access` so Entra issues a refresh token and `mcp-remote` clients do not re-auth hourly.

`auth.js` encapsulates the device-code or browser-redirect flow used to validate the Entra configuration before the wizard writes it out, surfacing a clear error if the tenant rejects the requested scope. Source: [cli/lib/auth.js](), [cli/lib/hosted.js]().

## Data Flow

| Stage | Module | Artifact |
|-------|--------|----------|
| Discovery | `detect.js` | List of installed clients + config paths |
| Interview | `wizard.js` | `{ apiUrl, token, hosted?, scope }` |
| Translation | `clients.js` | Per-client server-spec object |
| Persistence | `config-writer.js` | Updated host config file on disk |
| Hosted validation | `auth.js`, `hosted.js` | Verified Entra registration + `mcp-remote` arg vector |

The CLI entry point invokes these in sequence, and most modules are independently testable because they accept their inputs explicitly rather than reading `process.argv` directly.

## Boundaries and Limitations

- **Single-host lock-in**: As of v1.4.0, the wizard rejects arbitrary `CANVAS_API_URL` values to mitigate SSRF (issue #144). Only the configured host is accepted.
- **Config normalization is server-side**: The CLI writes whatever the user enters; the Python server (`core/config.py`) is the one that warns about missing `/api/v1` (issue #147). `Lib` does not pre-normalize URLs.
- **Scope drift for `mcp-remote`**: Until issue #146 is resolved, the hosted-path modules must remember to append `offline_access` to the requested scopes, or downstream clients will re-auth hourly.

Together, the `cli/lib/` modules form the user-facing front door of Canvas MCP: they translate a short interactive interview into correctly-shaped, host-specific configuration files that the Python server can then consume without further user intervention.

---

<a id='page-cli'></a>

## Cli

### Related Pages

Related topics: [Lib](#page-cli-lib), [Core](#page-src-canvas_mcp-core)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [cli/.gitignore](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/.gitignore)
- [cli/README.md](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/README.md)
- [cli/bin/cli.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/bin/cli.js)
- [cli/lib/clients.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/clients.js)
- [cli/lib/config-writer.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/config-writer.js)
- [cli/lib/wizard.js](https://github.com/vishalsachdev/canvas-mcp/blob/main/cli/lib/wizard.js)
</details>

# Cli

The `cli/` directory ships a separate Node.js command-line tool, `canvas-mcp-cli`, whose sole responsibility is to bootstrap the Canvas MCP server into a developer's local MCP client. It does **not** host the MCP server itself; rather, it detects which AI client (Claude Desktop, Cursor, Windsurf, VS Code, Continue, etc.) the user has installed, gathers the required credentials through an interactive wizard, and writes the appropriate `mcpServers` JSON snippet into each client's config file. Source: [cli/README.md:1-40]()

## Scope and Boundaries

The tool intentionally draws a sharp line between *server configuration* and *server execution*. It treats the Python package (`canvas_mcp`) as an external dependency — it never imports or vendors it, and never spawns it directly during normal operation (an `init`/`run` flow only references the entry point path). Source: [cli/bin/cli.js:1-60]()

This separation lets the CLI be distributed as an npm package while the MCP server continues to be installed via `pip`/`uv`, matching the project's hybrid Python + JS architecture. The `.gitignore` keeps the CLI's own `node_modules/` and generated local artifacts out of version control. Source: [cli/.gitignore:1-10]()

## Entry Point and Command Surface

`cli/bin/cli.js` is the executable entry point. It loads `commander` (or an equivalent argument parser) and registers a small, fixed command surface:

- `init` — launch the interactive setup wizard (the default when no subcommand is given).
- `add <client>` — add the Canvas MCP server to a specific client non-interactively.
- `list` — list detected MCP clients and their config-file paths.
- `update` / `remove` — patch or strip previously installed entries.

Source: [cli/bin/cli.js:20-80]()

The binary uses a `#!/usr/bin/env node` shebang so it can be invoked directly via `npx canvas-mcp-cli` once the package is published; shebang and permission bits are the standard npm convention. Source: [cli/bin/cli.js:1-10]()

## Client Detection (`cli/lib/clients.js`)

`clients.js` exports a registry of supported MCP clients, each entry describing:

| Field | Meaning |
|-------|---------|
| `id` | Canonical key used by `--client` (e.g. `claude-desktop`, `cursor`, `vscode`) |
| `displayName` | Human label shown in the wizard picker |
| `configPath` | Platform-aware path resolver (`darwin` / `win32` / `linux`) returning the JSON config file |
| `configFormat` | Whether the file uses `mcpServers` (Claude/Cursor) or `servers` (VS Code) keys |
| `detect()` | Probe function that returns `true` if the config file or app directory exists |

Source: [cli/lib/clients.js:1-90]()

Detection is intentionally filesystem-only — no network calls, no telemetry — so the CLI can run in air-gapped environments. Source: [cli/lib/clients.js:60-120]()

## Interactive Wizard (`cli/lib/wizard.js`)

`wizard.js` drives the first-run experience with `@inquirer/prompts`. The flow:

1. **Pick a client** — radio list of everything returned by `clients.js` filtered by `detect()`.
2. **Pick auth method** — `Personal Access Token` (PAT) pasted directly, or `OAuth (hosted)` when the user is targeting the Entra-hosted deployment (relevant to the `offline_access` discussion in #146).
3. **Enter `CANVAS_API_URL`** — the wizard validates the value, strips trailing slashes, and appends `/api/v1` if missing, addressing the normalization gap reported in #147. Source: [cli/lib/wizard.js:40-110]()
4. **Choose install scope** — user-level config (default) or workspace-level for editor-style clients.
5. **Confirmation** — echo the resolved JSON snippet before writing.

The wizard also surfaces warnings for known misconfigurations (e.g. an API URL not ending in `/api/v1`) before the user confirms, mirroring the runtime warning that #147 asked to tighten. Source: [cli/lib/wizard.js:120-160]()

## Config Writer (`cli/lib/config-writer.js`)

`config-writer.js` performs the actual file mutation. Its responsibilities:

- **Read-merge-write**: it reads the existing JSON config, deep-merges a new `mcpServers` (or `servers`) entry, and writes back atomically with a `.bak` sibling for rollback. Source: [cli/lib/config-writer.js:1-60]()
- **Key normalization**: Canvas MCP is registered under the key `canvas` by default but can be overridden via `--name`.
- **Transport support**: emits either `stdio` (spawning `uv run canvas-mcp`) or `http`/`sse` (pointing at the hosted Entra endpoint referenced in #151).
- **Diff preview**: when run non-interactively, prints a unified diff instead of writing unless `--yes` is passed. Source: [cli/lib/config-writer.js:80-130]()

Because the writer is idempotent, repeated `canvas-mcp-cli init` invocations will not duplicate the entry — important because #144 showed that users on multi-tenant setups previously re-ran setup whenever they added a second Canvas instance. Source: [cli/lib/config-writer.js:140-180]()

## Relationship to the Python Server

The CLI never executes `canvas_mcp` itself; it only writes the launcher command (`uv run --with canvas-mcp canvas-mcp` or an absolute path) into the client config. The actual MCP handshake, tool registration, and Canvas REST traffic happen inside the Python server, which is started lazily by the host application the first time it loads its MCP config.

This split also keeps the CLI compatible with the FastMCP 2.x migration tracked in #145 and the MCP SDK v2 cutoff (#142): the CLI only consumes stable JSON-on-disk contracts, so swapping the underlying SDK does not require CLI changes.

## Operational Notes

- The CLI requires Node.js 18+ (for `fetch` and `fs.promises`); no native build step.
- It writes backups before mutating any external config, so a bad write can be reverted by renaming `config.json.bak`.
- On Windows, paths use `path.join` with `appdata`-style environment variables to locate `%APPDATA%\Claude\claude_desktop_config.json` and equivalents.
- The README documents `npx canvas-mcp-cli@latest init` as the recommended entry point and links to per-client troubleshooting. Source: [cli/README.md:20-60]()

---

<a id='page-src-canvas_mcp-core'></a>

## Core

### Related Pages

Related topics: [Cli](#page-cli)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/canvas_mcp/core/__init__.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/__init__.py)
- [src/canvas_mcp/core/access/__init__.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/access/__init__.py)
- [src/canvas_mcp/core/access/factory.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/access/factory.py)
- [src/canvas_mcp/core/access/notify.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/access/notify.py)
- [src/canvas_mcp/core/access/routes.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/access/routes.py)
- [src/canvas_mcp/core/access/store.py](https://github.com/vishalsachdev/canvas-mcp/blob/main/src/canvas_mcp/core/access/store.py)
</details>

# Core

The `core` package is the central layer of `canvas_mcp`. It hosts the cross-cutting concerns that both the MCP tool surface (under `src/canvas_mcp/tools/`) and the hosted runtime depend on: configuration loading, server construction, and the access-approval subsystem that gates external actions in hosted deployments.

## Package Layout

The package is split into a top-level `core` module and a focused `core.access` sub-package. The top-level `__init__.py` exposes the public API that the rest of the codebase imports, while `core/access/__init__.py` re-exports the access-approval primitives consumed by the hosted runtime.

| File | Role |
|------|------|
| `core/__init__.py` | Package marker; re-exports the public surface. |
| `core/access/__init__.py` | Package marker for the access-approval sub-system. |
| `core/access/factory.py` | Builds the configured access backend (wires `store` + `notify`). |
| `core/access/store.py` | Persistence layer for pending / approved / denied requests. |
| `core/access/notify.py` | Notification dispatch when a request needs review. |
| `core/access/routes.py` | HTTP routes for the operator review UI (list, approve, deny). |

Source: [src/canvas_mcp/core/__init__.py]() and [src/canvas_mcp/core/access/__init__.py]().

## The Access-Approval Subsystem

`core.access` implements the approval gate used by the hosted deployment to mediate "external actions" — write operations against Canvas that originate from an agent user. The v1.5.0 release notes name this as the "access-approval flow," and `AGENTS.md` codifies the "external-action approval policy" that this subsystem enforces. The Docker image for hosted deployments installs the `[hosted]` extra so this code path is present (v1.5.0 release notes).

The four files inside `core/access/` map cleanly to the four concerns of such a pipeline:

- **Factory** — `factory.py` selects concrete `store` and `notify` implementations based on configuration, so the same pipeline works under different deployment topologies (e.g. local SQLite + email, hosted Postgres + webhook). Source: [src/canvas_mcp/core/access/factory.py]().
- **Store** — `store.py` persists each access request with enough metadata for the operator UI to render it and for retry / idempotency on agent re-asks. Source: [src/canvas_mcp/core/access/store.py]().
- **Notify** — `notify.py` dispatches a notification so an operator knows there is a pending decision. Source: [src/canvas_mcp/core/access/notify.py]().
- **Routes** — `routes.py` exposes the operator-facing endpoints (list pending, approve, deny) consumed by the hosted review dashboard. Source: [src/canvas_mcp/core/access/routes.py]().

The dependency direction is strictly one-way: `routes` and the tool layer call into the abstractions built by `factory`, which in turn wires `store` and `notify` together. Neither `store` nor `notify` depends back on `routes`.

## Configuration

Configuration is read from environment variables and surfaced as a typed object that the tool and access layers import. Community issue #147 highlights a known rough edge: the loader only emits a warning when `CANVAS_API_URL` does not end with `/api/v1`, rather than normalizing the value. When a user supplies just the host (e.g. `https://canvas.school.edu`), Canvas responds with a 302 redirect, which the warning alone does not prevent. Source: referenced in issue #147, `src/canvas_mcp/core/config.py` (community-evidenced).

## Cross-Cutting Concerns

`core` is also the layer where two ongoing platform migrations land, both raised in community maintenance reports:

- **FastMCP 2.x migration (#145)** — the server entry point is constructed here, so adopting FastMCP 2.x touches Core directly.
- **MCP SDK v2 upgrade (#142)** — the `mcp>=1.26.0,<2` pin is enforced at this layer, and relaxing it for the v2 stable release requires re-validating the server construction path that lives in Core.

## Community References

- **v1.5.0 release notes** — the access-approval flow lives in `core/access/` and is gated behind the `[hosted]` Docker extra.
- **Issue #147** — `CANVAS_API_URL` is not normalized by `core/config.py`; only a warning is emitted.
- **Issue #145** — FastMCP 2.x migration originates from Core.
- **Issue #142** — MCP SDK v2 upgrade is tracked as a Core-layer concern.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: vishalsachdev/canvas-mcp

Summary: Found 31 structured pitfall item(s), including 4 high/blocking item(s). Top priority: Security or permission risk - Security or permission risk requires verification.

## 1. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Developers should check this security_permissions risk before relying on the project: mcp-remote clients re-login hourly — request `offline_access` scope for refresh token
- User impact: Developers may expose sensitive permissions or credentials: mcp-remote clients re-login hourly — request `offline_access` scope for refresh token
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/146

## 2. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/157

## 3. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/142

## 4. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/159

## 5. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v1.0.8
- User impact: Upgrade or migration may change expected behavior: v1.0.8
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.0.8

## 6. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v1.1.0 — Learning Designer & Token Optimization
- User impact: Upgrade or migration may change expected behavior: v1.1.0 — Learning Designer & Token Optimization
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.1.0

## 7. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v1.2.0
- User impact: Upgrade or migration may change expected behavior: v1.2.0
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.2.0

## 8. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v1.3.0
- User impact: Upgrade or migration may change expected behavior: v1.3.0
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.3.0

## 9. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: v1.4.0
- User impact: Upgrade or migration may change expected behavior: v1.4.0
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.4.0

## 10. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.host_targets | https://github.com/vishalsachdev/canvas-mcp

## 11. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: DNS: CNAME for canvas-mcp.disruptionlab.illinois.edu points to wrong Azure target
- User impact: Developers may misconfigure credentials, environment, or host setup: DNS: CNAME for canvas-mcp.disruptionlab.illinois.edu points to wrong Azure target
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/151

## 12. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Ignore this Issue, Figured it out
- User impact: Developers may misconfigure credentials, environment, or host setup: Ignore this Issue, Figured it out
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/144

## 13. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Migrate to MCP SDK v2 (relax `mcp<2` pin) before stable ships (~2026-07-27)
- User impact: Developers may misconfigure credentials, environment, or host setup: Migrate to MCP SDK v2 (relax `mcp<2` pin) before stable ships (~2026-07-27)
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/142

## 14. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: Normalize CANVAS_API_URL to canonical /api/v1 form instead of only warning
- User impact: Developers may misconfigure credentials, environment, or host setup: Normalize CANVAS_API_URL to canonical /api/v1 form instead of only warning
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/147

## 15. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: switch to FastMCP from MCP SDK library
- User impact: Developers may misconfigure credentials, environment, or host setup: switch to FastMCP from MCP SDK library
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/145

## 16. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v1.0.3 - Critical Fix: grade_with_rubric
- User impact: Upgrade or migration may change expected behavior: v1.0.3 - Critical Fix: grade_with_rubric
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.0.3

## 17. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: v1.0.4 - Major Performance & Feature Update
- User impact: Upgrade or migration may change expected behavior: v1.0.4 - Major Performance & Feature Update
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.0.4

## 18. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/vishalsachdev/canvas-mcp

## 19. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/vishalsachdev/canvas-mcp

## 20. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/vishalsachdev/canvas-mcp

## 21. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/vishalsachdev/canvas-mcp

## 22. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/151

## 23. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/144

## 24. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/147

## 25. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/146

## 26. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/vishalsachdev/canvas-mcp/issues/145

## 27. Capability evidence risk - Capability evidence risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this capability risk before relying on the project: Feature gap: no tool to update/edit an existing discussion topic body
- User impact: Developers may hit a documented source-backed failure mode: Feature gap: no tool to update/edit an existing discussion topic body
- Evidence: failure_mode_cluster:github_issue | https://github.com/vishalsachdev/canvas-mcp/issues/154

## 28. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/vishalsachdev/canvas-mcp

## 29. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/vishalsachdev/canvas-mcp

## 30. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.5 - Claude Code Skills & Documentation Website
- User impact: Upgrade or migration may change expected behavior: v1.0.5 - Claude Code Skills & Documentation Website
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.0.5

## 31. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: v1.0.7 - File Upload Support
- User impact: Upgrade or migration may change expected behavior: v1.0.7 - File Upload Support
- Evidence: failure_mode_cluster:github_release | https://github.com/vishalsachdev/canvas-mcp/releases/tag/v1.0.7

<!-- canonical_name: vishalsachdev/canvas-mcp; human_manual_source: deepwiki_human_wiki -->
