Skip to main content

uoft-quercus-mcp

Unofficial MCP server for University of Toronto students: Quercus (Canvas) tools via a personal access token, plus public Timetable Builder helpers for schedule search and conflict checks.

Disclaimer

This project is not affiliated with, endorsed by, or supported by the University of Toronto.

  • Quercus tools use the Canvas API with a personal access token you create. That is not an official Quercus product.
  • Timetable tools use the public Timetable Builder HTTP API (separate from Quercus). U of T may change, rate-limit, or block access at any time.

Use at your own risk and respect upstream terms of use.

What it does

Quercus (requires QUERCUS_ACCESS_TOKEN):

  • Verify your Quercus identity
  • List enrolled courses
  • Todo items and upcoming events
  • Assignments and announcements (announcements use term start, else last 365 days, through today)
  • Modules and course files
  • Download files and extract text from PDF/DOCX/plain text (no OCR)

Timetable Builder (no Quercus token):

  • Discover current sessions, divisions, campuses, delivery modes, and course levels
  • Search courses by code or title
  • Fetch section, meeting, instructor, and enrolment details
  • Deterministically check selected sections for time overlaps and transition gaps

What it does not do

  • UTORid / password login, cookie scraping, or session hijacking
  • Hosted OAuth / multi-user Quercus product (personal token only for now)
  • Course enrolment or waitlist changes
  • Degree / prerequisite / eligibility decisions
  • Exam schedules
  • Saved timetables, accounts, or persistence
  • OCR for scanned PDFs/images
  • Automatic schedule generation inside the server

Privacy

  • Quercus: put your personal access token only in the MCP server env (for example Cursor mcp.json). The token is never logged or returned in tool output. Do not commit or share it.
  • Downloads stay on your machine under QUERCUS_DOWNLOAD_DIR.
  • Timetable tools call the public Timetable Builder API only — no U of T credentials required.

Prerequisites

  • Python 3.11+
  • uv (recommended) or pip

Installation

The published package on PyPI is the recommended install. uvx runs it without a local clone:

uvx uoft-quercus-mcp

Or install it:

uv tool install uoft-quercus-mcp
# or
pip install uoft-quercus-mcp

For a local checkout, see Development.

Create a Quercus personal access token

  1. Sign in to Quercus.
  2. Open Account → Settings → New Access Token (wording may vary by campus/theme).
  3. Copy the token once when it is shown.
  4. Put it only in MCP env as QUERCUS_ACCESS_TOKEN — never in chat, commits, or screenshots.

Background on Canvas tokens: How do I manage API access tokens? (campus Quercus help may differ slightly).

Without a token, Timetable tools still work; Quercus tools return quercus_auth_missing.

Cursor MCP configuration

Add this to your Cursor MCP settings:

{
  "mcpServers": {
    "uoft-quercus": {
      "command": "uvx",
      "args": ["uoft-quercus-mcp"],
      "env": {
        "QUERCUS_ACCESS_TOKEN": "your-quercus-personal-access-token"
      }
    }
  }
}

A deprecated console-script alias uoft-timetable-mcp still points at the same entry point for old configs. Prefer uoft-quercus-mcp.

After restarting MCP, Cursor should discover Quercus tools (token required) and Timetable Builder (TTB) tools:

  • Quercus: quercus_whoami, quercus_list_courses, quercus_list_todo, quercus_list_assignments, quercus_list_announcements, quercus_list_modules, quercus_list_files, quercus_get_file
  • Timetable Builder (TTB): ttb_get_reference_data, ttb_search_courses, ttb_get_course_details, ttb_check_conflicts

Quick start prompts

  • “What’s due on Quercus?”
  • “List modules for MATA22 and open the past quiz PDF, then help with question 4.”
  • “Search Fall timetable for CSC108H1 and check conflicts for these lecture/tutorial sections.”

Tools

Quercus tools

Tool Purpose
quercus_whoami Verify the token / identity
quercus_list_courses Canvas id + course_code + name
quercus_list_todo Todo items and upcoming events
quercus_list_assignments Course-scoped assignments (full list)
quercus_list_announcements Course-scoped; term start (else last 365 days) through today
quercus_list_modules Modules / materials map (file_id on File items)
quercus_list_files Course Files area
quercus_get_file mode=metadata|text|download (PDF/DOCX/text extraction; no OCR)

Course-scoped tools accept a Canvas id, code fragment (MATA22), or name fragment. Prefer ids from quercus_list_courses when ambiguous.

Past quiz PDF flow: quercus_list_modules or quercus_list_filesquercus_get_file with mode=text.

Timetable Builder (TTB) tools

Tool Purpose
ttb_get_reference_data Valid sessions, divisions, campuses, delivery modes, course levels (not hard-coded)
ttb_search_courses Search by code or title; requires session(s) + division(s); concise paginated summaries
ttb_get_course_details Full section/meeting details; optional section_code is term half (F/S/Y), not LEC/TUT
ttb_check_conflicts Deterministic overlap / transition checks on selected sections

Prefer full UofT course codes when known (e.g. CSC108H1, CSCA08H3). Short codes are expanded using the selected division from ttb_get_reference_data (ARTSC / APSC St. George, SCAR UTSC, ERIN UTM).

Before claiming a schedule is verified, call ttb_check_conflicts with every selected section and require has_conflicts false, empty transition_violations, and is_complete true.

Data sources and freshness

  • Quercus: https://q.utoronto.ca (Canvas API; needs personal access token)
  • Timetable Builder: https://api.easi.utoronto.ca/ttb
  • Reference data is cached in memory for 15 minutes (TIMETABLE_REFERENCE_CACHE_TTL_SECONDS)
  • Search / details / conflicts fetch current upstream data
  • Enrolment numbers, rooms, and Quercus content can change; treat responses as point-in-time

Environment variables

Variable Default Purpose
QUERCUS_ACCESS_TOKEN (unset) Quercus personal access token
QUERCUS_BASE_URL https://q.utoronto.ca Quercus site root
QUERCUS_CONNECT_TIMEOUT_SECONDS 5 Quercus connect timeout
QUERCUS_READ_TIMEOUT_SECONDS 20 Quercus read timeout
QUERCUS_MAX_ATTEMPTS 3 Quercus retry attempts
QUERCUS_MAX_PAGE_SIZE 100 Canvas per_page cap
QUERCUS_MAX_CONCURRENCY 5 Max concurrent module-item fetches
QUERCUS_DOWNLOAD_DIR ~/.cache/uoft-quercus-mcp/files Local download directory
QUERCUS_COURSE_CACHE_TTL_SECONDS 120 Course-list resolver cache TTL
QUERCUS_MAX_DOWNLOAD_BYTES 26214400 Max file download size (25 MiB)
QUERCUS_MAX_TEXT_CHARS 200000 Max extracted text characters
TIMETABLE_BASE_URL https://api.easi.utoronto.ca/ttb Upstream API root
TIMETABLE_CONNECT_TIMEOUT_SECONDS 5 Connect timeout
TIMETABLE_READ_TIMEOUT_SECONDS 20 Read timeout
TIMETABLE_REFERENCE_CACHE_TTL_SECONDS 900 Reference-data cache TTL
TIMETABLE_MAX_PAGE_SIZE 50 Max search page size
TIMETABLE_MAX_CONCURRENCY 5 Max concurrent course lookups

Development

git clone git@github.com:skhdemo/uoft-quercus-mcp.git
cd uoft-quercus-mcp
uv sync

If your local folder is still named uoft-timetable-mcp, that is fine until you rename it.

Run the server from the checkout:

uv run uoft-quercus-mcp
# or
uv run python -m uoft_quercus_mcp

Local Cursor config (no PyPI install):

{
  "mcpServers": {
    "uoft-quercus": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/uoft-quercus-mcp",
        "run",
        "uoft-quercus-mcp"
      ],
      "env": {
        "QUERCUS_ACCESS_TOKEN": "your-quercus-personal-access-token"
      }
    }
  }
}

Lint and test:

uv run ruff format .
uv run ruff check .
uv run pyright
uv run pytest
uv run pytest --cov

Optional live API smoke tests (excluded by default):

uv run pytest -m live
uv run pytest -m live_quercus

Troubleshooting

Quercus auth missing / rejected

  • Confirm QUERCUS_ACCESS_TOKEN is set in the MCP server environment (Cursor mcp.json env does not apply to a plain shell pytest)
  • Regenerate the token in Quercus if it was revoked
  • Some Canvas features may return quercus_forbidden depending on course permissions

Timeouts / upstream unavailable

  • Retry later; transient 429 / 5xx / network timeouts are retried a few times
  • Check network access to q.utoronto.ca and/or api.easi.utoronto.ca
  • Increase QUERCUS_READ_TIMEOUT_SECONDS or TIMETABLE_READ_TIMEOUT_SECONDS if needed

No timetable search results

  • Confirm session and division values via ttb_get_reference_data (do not guess old term codes)
  • Try a broader title query, or a full course code like CSC108H1
  • Empty results (courses: [], total: 0) are valid — not an error

Local folder still named uoft-timetable-mcp

The GitHub repo is uoft-quercus-mcp. Renaming your local checkout folder is optional; if you use the local Cursor config, update the --directory path.

License

See LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uoft_quercus_mcp-0.1.0.tar.gz (40.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uoft_quercus_mcp-0.1.0-py3-none-any.whl (50.8 kB view details)

Uploaded Python 3

File details

Details for the file uoft_quercus_mcp-0.1.0.tar.gz.

File metadata

  • Download URL: uoft_quercus_mcp-0.1.0.tar.gz
  • Upload date:
  • Size: 40.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for uoft_quercus_mcp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 3f0b660e19b43e2d8df12ab3e58a6148e7c9bde66e80b33be4747634543db2f0
MD5 507096dbfbc5e1e4f89c3dc376ed43e6
BLAKE2b-256 19b0265e947f23d7eb44ecc4ee55f0951c8e512018e84c1af27d08a1e91fa59a

See more details on using hashes here.

File details

Details for the file uoft_quercus_mcp-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: uoft_quercus_mcp-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 50.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for uoft_quercus_mcp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6170c4a946be9609a4d7e4de2761c67e0c01bd9a5a39ea0283829eca74d70083
MD5 2411e351d8226d1b5bc97f4234123b6a
BLAKE2b-256 6faa6f6ba8ec177a7a7653c629d9a1a14ba1c9a9bf0490b23ced721db6c5334f

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page