Skip to main content
Glama
README.md
# Canvas LMS MCP Server

A Python MCP server that exposes Canvas LMS academic data as callable tools for AI agents.

---

## What is MCP?

**Model Context Protocol (MCP)** is an open standard developed by Anthropic that defines how AI models communicate with external tools and data sources. Instead of embedding all logic inside a prompt, an AI agent discovers available tools at runtime and calls them by name with typed arguments — just like a function call.

MCP separates concerns cleanly:

```
AI Agent  ──(tool call)──►  MCP Server  ──(HTTP)──►  Canvas LMS API
           ◄──(result)────              ◄──(JSON)────
```

The agent never knows or cares how Canvas authentication works; it only calls `get_courses()` and receives structured data.

---

## Architecture

```
canvas-mcp/
├── main.py           # MCP server — registers tools and starts the server
├── canvas_client.py  # Canvas API client — authentication, pagination, retries
├── requirements.txt
├── .env.example
└── README.md
```

### `canvas_client.py` — CanvasClient

The `CanvasClient` class centralises all HTTP communication with Canvas:

| Concern | Implementation |
|---|---|
| Authentication | `Authorization: Bearer <token>` header on every request |
| Pagination | Parses `Link: <url>; rel="next"` headers and accumulates pages automatically |
| Retries | `urllib3.Retry` with 3 attempts, exponential backoff, on 429/5xx responses |
| Error surface | All failures raise `CanvasAPIError` with the HTTP status and body |

### `main.py` — FastMCP Server

Uses `FastMCP` from the `mcp` package to register Python functions as MCP tools. Each tool:

1. Calls one or more `CanvasClient` methods.
2. Filters the raw Canvas response to the fields the agent actually needs.
3. Returns a plain Python `list[dict]` or `dict` — always JSON-serialisable.

---

## Canvas Integration

### Authentication

Canvas uses **Personal Access Tokens** for API authentication. Once generated in Canvas Settings, the token is sent as a Bearer token on every request:

```
Authorization: Bearer <CANVAS_API_TOKEN>
```

### Endpoints Used

| MCP Tool | Canvas Endpoint |
|---|---|
| `get_courses` | `GET /api/v1/courses` |
| `get_assignments` | `GET /api/v1/courses/{id}/assignments` |
| `get_upcoming_events` | `GET /api/v1/planner/items` |
| `get_course_grades` | `GET /api/v1/courses/{id}/enrollments` |
| `get_course_summary` | Combines courses + assignments + enrollments |

### Pagination

Canvas paginates results via `Link` response headers:

```
Link: <https://canvas.example.com/api/v1/courses?page=2>; rel="next"
```

`CanvasClient._get()` follows these automatically, collecting every page into a single list before returning.

---

## Installation

### Prerequisites

- Python 3.11 or later
- A Canvas LMS account with API access

### Steps

```bash
# 1. Clone / enter the project
cd canvas-mcp

# 2. Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Configure environment variables
cp .env.example .env
# Edit .env with your Canvas URL and token
```

---

## Configuration

Copy `.env.example` to `.env` and fill in your values:

```dotenv
# Your institution's Canvas domain
CANVAS_BASE_URL=https://canvas.example.edu

# Personal Access Token from Canvas Account → Settings → New Access Token
CANVAS_API_TOKEN=your_token_here
```

The server validates both variables at startup and exits with a clear error message if either is missing.

---

## Running the MCP Server

```bash
# Activate venv if not already active
source .venv/bin/activate

# Start the server (communicates over stdio)
python main.py
```

The server speaks the MCP stdio transport. To wire it into **Claude Code**, add it to your `.claude/settings.json`:

```json
{
  "mcpServers": {
    "canvas": {
      "command": "python",
      "args": ["/absolute/path/to/canvas-mcp/main.py"],
      "env": {
        "CANVAS_BASE_URL": "https://canvas.example.edu",
        "CANVAS_API_TOKEN": "your_token_here"
      }
    }
  }
}
```

Or set `CANVAS_BASE_URL` / `CANVAS_API_TOKEN` in your shell environment and omit the `env` block.

---

## Available MCP Tools

### `get_courses()`
Returns all active courses for the authenticated user.

### `get_assignments(course_id)`
Returns all assignments for the specified course.

### `get_upcoming_events()`
Returns upcoming items from the Canvas Planner (assignments, calendar events, etc.).

### `get_course_grades(course_id)`
Returns current score and letter grade for every enrolled student in the course.

### `get_course_summary(course_id)`
Aggregates course info, assignments, and grades into a single summary including:
- Total assignments
- Next upcoming assignment
- Number of enrolled students
- Average score and letter grade

---

## Example Agent Prompts

```
List my available courses.
```

```
Show assignments for course 123.
```

```
What deadlines do I have this week?
```

```
Show grade information for course 123.
```

```
Generate a summary of course 123.
```

---

## Error Handling

- All tools catch `CanvasAPIError` and return `{"error": "..."}` rather than raising, so the agent can surface the message gracefully.
- HTTP errors (4xx/5xx) include the Canvas response body in the error message.
- Transient failures (429, 502, 503, 504) are retried automatically up to 3 times with exponential backoff.