Skip to main content
Glama

Camino MCP

A local Model Context Protocol (MCP) server for Santa Clara University's Camino (Canvas LMS). Read courses, assignments and instructions, pages, discussions, announcements, Canvas Inbox messages, and course files; optionally download files to an existing local directory. Every user runs their own copy with their own Camino token. This repository is not affiliated with or endorsed by Santa Clara University or Instructure.

No shared account or hosted service: The server runs over local stdio. It makes HTTPS GET requests to https://camino.instructure.com/, plus credential-free GET requests to allowlisted Canvas file CDN hosts when downloading. No token, personal coursework, or institutional data is bundled with the code. Your chosen AI client may send tool results to its model provider; check its data policies and your institution's rules before connecting.

Web vs. local: A GitHub URL is source code, not an MCP endpoint. You cannot upload this repository to ChatGPT, Gemini, or Claude in a browser and have its stdio tools run there. See Browser-based ChatGPT, Gemini, and Claude for alternatives and limitations. Local clients (including Claude Code, Codex CLI, Gemini CLI, Hermes, Claude Desktop, and supported ChatGPT desktop clients) can run it directly.

Quick start (about 10 minutes)

  1. Install uv (it installs Python for you): follow https://docs.astral.sh/uv/getting-started/installation/. On macOS/Linux: curl -LsSf https://astral.sh/uv/install.sh | sh. On Windows (PowerShell): powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex".

  2. Download this project and install it (commands below).

  3. Create your Camino token — see Getting your Camino API token.

  4. Connect your AI app — pick yours under Local AI clients. Not sure? Claude Desktop is the easiest for non-programmers.

  5. Restart the AI app and ask: "Check my Camino setup", then "What's due this week?"

Ask your AI assistant to help with any step — this README includes a section written for it.

Related MCP server: ntnu-mcp

Requirements and installation

  • Python 3.11+ and uv installed on the machine that will run the MCP server.

  • A Camino account allowed to create an API access token. See Getting your Camino API token. Each person must create their own token.

git clone https://github.com/carlosceja27/camino-mcp.git
cd camino-mcp
uv sync --locked
# Launches the MCP stdio server; your MCP client normally starts this for you:
uv run --locked camino-mcp

Getting your Camino API token

  1. Sign in at https://camino.instructure.com with your SCU account.

  2. In the left global navigation bar, click Account (your profile picture), then Settings.

  3. Scroll to Approved Integrations and click + New Access Token.

  4. For Purpose, enter something recognizable, such as Camino MCP (local).

  5. Set an Expiration date — a short window such as the current term or less is recommended. Leaving it blank creates a token that does not expire.

  6. Click Generate Token.

  7. Copy the token immediately. Canvas shows the full token only once; after you close the dialog, you would need to regenerate it.

  8. Store it privately and supply it as CAMINO_API_TOKEN (see below).

To revoke a token later, return to Account → Settings → Approved Integrations, click Details beside the token, then Delete. Do this if the token is ever exposed or no longer needed.

If you don't see + New Access Token, or Camino says you are not authorized to create tokens, your institution may have disabled user-generated tokens. Contact SCU Technology Help; this server cannot work around that restriction.

The token acts as you: anyone with it can read your Camino courses, messages, and grades and use any other access your account has in Canvas. Treat it like a password.

Note for AI assistants helping a user set this up

If a tool returns CAMINO_API_TOKEN is not set or Camino rejected the API token, walk the user through the steps above, one step at a time and in plain language. Ask which AI app and operating system they use, then point them to the matching section under Local AI clients. After they restart the app, call check_setup to confirm it works. Never ask the user to paste their token into the chat, and never write it into repository files, shared configs, command-line arguments, or logs. Instead, direct them to enter it themselves using one of the private methods below (for example, read -r -s CAMINO_API_TOKEN; export CAMINO_API_TOKEN in a terminal, or their MCP client's private environment settings), then restart the MCP client so the server picks it up. If the user already pasted a token into a chat, recommend revoking it and generating a new one.

Supplying the token

Set CAMINO_API_TOKEN privately in the MCP server process environment. For a temporary terminal session, read -r -s CAMINO_API_TOKEN; export CAMINO_API_TOKEN (some shells require read -s CAMINO_API_TOKEN instead). For regular use, configure a local, access-controlled secret manager or client-specific environment. Do not put a real token in this repository, shared/project configs, command-line arguments, AI chats, or shell history. The server does not load .env or macOS Keychain automatically; if a token is missing, tools report an error without calling Camino. If your AI client is launched from the desktop, it may not inherit your shell's environment.

Use absolute paths in the examples below: replace /absolute/path/to/uv with the result of command -v uv, and /absolute/path/to/camino-mcp with your clone's absolute path. Keep client configuration outside the public repository and do not commit tokens. uv run --locked --directory ... uses the clone's lockfile without installing dev dependencies. Windows users: use absolute Windows paths and the appropriate executable name for uv (typically uv.exe); environment injection differs by shell/client.

Local AI clients

Claude Code

For a private user-level configuration rather than a project-shared .mcp.json:

claude mcp add --scope user --transport stdio camino -- /absolute/path/to/uv run --locked --directory /absolute/path/to/camino-mcp camino-mcp

Start Claude Code from a session where CAMINO_API_TOKEN is already available to it, then type /mcp to check connection. Do not use --env CAMINO_API_TOKEN=... with your actual token: client config could retain it. Claude Code MCP docs.

Codex CLI (and supported ChatGPT desktop MCP configuration)

In your private ~/.codex/config.toml:

[mcp_servers.camino]
command = "/absolute/path/to/uv"
args = ["run", "--locked", "--directory", "/absolute/path/to/camino-mcp", "camino-mcp"]
env_vars = ["CAMINO_API_TOKEN"]

Launch Codex with that variable available in its environment; env_vars forwards the named variable without persisting its value in the TOML file. Check /mcp in Codex. OpenAI also documents a ChatGPT desktop app MCP settings panel with a local STDIO option; availability may vary by product and release. This is not ChatGPT in a browser. Codex MCP docs.

Gemini CLI

In your private ~/.gemini/settings.json, merge the following entry into the existing top-level mcpServers object (do not replace other settings):

{
  "mcpServers": {
    "camino": {
      "command": "/absolute/path/to/uv",
      "args": ["run", "--locked", "--directory", "/absolute/path/to/camino-mcp", "camino-mcp"],
      "env": {"CAMINO_API_TOKEN": "$CAMINO_API_TOKEN"},
      "trust": false
    }
  }
}

Launch Gemini CLI from a session with CAMINO_API_TOKEN set. Gemini CLI explicitly expands $CAMINO_API_TOKEN from its environment; verify with /mcp list. Gemini CLI MCP docs.

Hermes Agent

Hermes filters tokens out of the environment inherited by stdio MCP subprocesses. Add the server using the documented mcp_servers key, through your private Hermes configuration workflow:

mcp_servers:
  camino:
    command: "/absolute/path/to/uv"
    args: ["run", "--locked", "--directory", "/absolute/path/to/camino-mcp", "camino-mcp"]

This will not authenticate by itself. Users must explicitly supply CAMINO_API_TOKEN to this subprocess using their own secure, local-only credential injection (for example, a user-owned launcher that retrieves a token from an OS secret store, or private env configuration protected by filesystem permissions). Do not assume an exported shell variable is forwarded automatically, and never commit a credential-bearing configuration. Restart Hermes and check that its mcp_camino_* tools appear. Hermes native MCP docs.

Claude Desktop and other local stdio clients

In Claude Desktop open Settings → Developer → Edit Config. This opens your private claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\). Add:

{
  "mcpServers": {
    "camino": {
      "type": "stdio",
      "command": "/absolute/path/to/uv",
      "args": ["run", "--locked", "--directory", "/absolute/path/to/camino-mcp", "camino-mcp"],
      "env": {"CAMINO_API_TOKEN": "paste-your-token-here"}
    }
  }
}

Desktop-launched apps usually do not inherit shell exports, so the env entry is the simplest option. That file lives only in your user account; never share, sync, or commit it, and revoke the token if the file is exposed. Fully quit and reopen Claude Desktop, then ask "Check my Camino setup." Claude Desktop local MCP servers run on your machine (unlike its web connectors). Each client has its own config path and support level. Claude local MCP help.

Browser-based ChatGPT, Gemini, and Claude

Browser product

What it expects

Can this repository be uploaded or pasted directly?

ChatGPT web MCP apps

An accessible remote MCP endpoint and eligible account/workspace features; OpenAI documents Secure MCP Tunnel for supported products.

No. A local stdio process is not a remote endpoint.

Gemini web custom apps

An MCP server URL; access is subject to Google's account, region, language, and feature requirements.

No. A GitHub clone/stdio command is not a URL for an MCP service.

Claude web custom connectors

A reachable remote MCP URL from Anthropic's cloud, subject to plan and workspace rules.

No. Claude web cannot launch your local process.

This project does not implement a remote transport, OAuth, user isolation, or a hosted endpoint. To use a browser product, you would need to deploy and secure a compatible remote MCP service (or a supported user-controlled tunnel/bridge where documented), with appropriate HTTPS, access control, per-user authentication, and institutional approval. Do not simply expose this stdio server or place a shared Camino token in an unauthenticated public wrapper. We do not provide or operate such a service, and we do not claim these browser paths are tested with this project. A self-hosted bridge also changes the privacy and maintenance model; local clients are the supported path here.

Local models (Ollama, LM Studio, etc.)

Any local stdio MCP client works. For small models: IDs may be sent as numbers or strings, all tools return short JSON with complete/error, and the server sends usage instructions during MCP initialization. Models with at least 7–8B parameters and native tool calling (for example Qwen 2.5/3, Llama 3.1+) work best. If a model loops or picks the wrong tool, ask directly: "Use the upcoming tool."

Things to ask

  • "Check my Camino setup." · "What courses am I in?"

  • "What's due in the next 3 days?" · "Do I have anything overdue?"

  • "What are my grades?" · "Show the instructions for the Week 2 homework in Career Communication."

  • "Any new announcements in Political Philosophy?" · "Download the syllabus PDF to ~/Downloads."

Tools and behavior

  • check_setup: verifies the token by reading your own Camino profile name; use it after setup.

  • list_courses: merges paginated active, invited/pending, and favorite courses, deduplicated by numeric ID; unstarred courses stay included. Includes the term name and course end date when available. Archived active enrollments may appear.

  • list_assignments(course_id, bucket?): accepts a numeric course ID (number or string) and requests submission metadata. Supported Canvas buckets: future, past, overdue, upcoming, unsubmitted, ungraded, undated.

  • upcoming(days=7): scans active courses for dated assignments due within the next 1–31 rolling 24-hour days that are not submitted or excused.

  • overdue(include_ended_courses=false): past-due work you have not turned in on Camino. It leaves out paper/in-class/no-submission items (unless Canvas marks them missing), excused work, and courses whose end date has passed. Set include_ended_courses=true to include those courses.

  • grades: current enrollment grade/score, when Canvas exposes it; not a grade transcript.

  • get_assignment(course_id, assignment_id): full assignment HTML instructions/description and submission information.

  • list_pages(course_id) / get_page(course_id, page_url): course page index and full page HTML body. page_url is the slug from list_pages, not a full URL.

  • list_discussions(course_id) / get_discussion(course_id, topic_id): discussion topics and initial topic message; replies are not included.

  • list_announcements(course_id): course announcements, including message bodies.

  • list_conversations(course_id) / get_conversation(conversation_id): Canvas Inbox threads filtered by course, then full messages for a selected thread. The detail call accepts a conversation ID accessible to the token; it is not course-scoped.

  • list_files(course_id) / download_file(course_id, file_id, destination_dir): inspect course file IDs and download a selected file to an existing absolute directory on the machine running the MCP server. No overwrites; 20 MB maximum; filename and downloaded size checked against Canvas metadata. The Canvas-managed signed CDN chain is followed at most three hops without forwarding the bearer token; any other host fails. The file is saved locally, not sent as an MCP attachment or uploaded to the model.

Cross-course scans skip courses you can't access (for example unpublished) and return them in skipped_courses with "complete": false; any other failure, such as a Camino outage, stops the scan with an error. No partial result is labeled complete. Successful tool responses include "complete": true; errors include "complete": false. Course content HTML is returned as data, not executed or treated as instructions. List responses omit arbitrary Canvas fields and signed file URLs. Only Camino HTTPS links are emitted in assignment summaries. Undated/invalid-date work is omitted from date-window tools; use list_assignments to inspect it. Dates are compared as timezone-aware instants.

Security and limitations

  • API calls are limited to Camino HTTPS; file downloads allow only a Canvas-hosted redirect to *.canvas-user-content.com and never forward credentials to that CDN. No arbitrary URL fetches. Pagination is restricted to the same endpoint. Requests time out; rate-limited responses (429, or Canvas's 403 "Rate Limit Exceeded") get two short retries; pagination is capped at 20 pages and fails rather than silently truncating results.

  • Read-only means no Canvas writes; download_file does write one new local file in the requested directory. Your AI client may still transmit returned content to its model provider. Use only a trusted client and handle student information under applicable institutional rules.

  • Automated tests use synthetic Canvas responses. A live Camino smoke test checked representative read endpoints and a redirect, but course-specific permissions, availability, file types, and Inbox content vary. Some courses return 404 for Pages when that feature is unavailable; other Canvas file CDNs may be rejected by the strict allowlist.

  • Do not paste tokens or full private tool responses into public bug reports.

Troubleshooting

What you see

What to do

CAMINO_API_TOKEN is not set

The AI app isn't passing your token. Add it to that app's MCP settings (see your client above) and fully restart the app.

Camino rejected the API token

The token expired, was deleted, or was copied incompletely. Create a new one and replace the old value.

Camino tools don't appear at all

Check that the uv and project paths in the config are absolute and correct (command -v uv), then restart. Run uv run --locked camino-mcp in the project folder to see startup errors (press Ctrl+C to stop).

skipped_courses in results

Those courses aren't published or accessible to you yet; everything else is still listed.

rate-limiting

Wait a minute and ask again.

Could not reach Camino

Check your internet connection or whether Camino is down.

An assignment seems missing from overdue

Paper/in-class items, excused work, and ended courses are left out. Ask for list_assignments for that course, or overdue with ended courses included.

Development

uv sync --extra dev --locked
uv run --locked ruff check src tests
uv run --locked ruff format --check src tests
uv run --locked pytest -q --cov=camino_mcp --cov-report=term-missing
uv build --no-sources

The suite uses synthetic Canvas responses and an offline MCP stdio handshake. Contributions welcome; please include tests, and do not submit real coursework or tokens. The repository is distributed under Apache License 2.0. The separate Camino Assistant skill inspired this implementation but is not bundled here.

Available Tools

5 tools
gradesA

Current grade/score metadata by enrolled course, when visible to the token.

Inputs: no named parameters.

list_assignmentsB

Read one numeric course ID's assignment metadata; optional Canvas assignment bucket.

Inputs: course_id (required), bucket.

list_coursesA

List all active, pending, and favorite courses (including unstarred courses).

Inputs: no named parameters.

overdueB

Unsubmitted past-due assignments across all enrolled courses.

Inputs: no named parameters.

upcomingC

Unsubmitted assignments due within the next 1–31 days across all enrolled courses.

Inputs: days.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 5 tools

    Disambiguation5/5

    Each tool has a clearly distinct purpose: list_courses covers courses, list_assignments covers per-course assignments, upcoming/overdue are filtered views of unsubmitted assignments, and grades covers course-level scores. No overlap or ambiguity in intent.

    Naming Consistency3/5

    The naming is mixed but still readable: list_courses and list_assignments follow a verb_noun pattern, while upcoming, overdue, and grades use single descriptive terms. This inconsistency could cause slight uncertainty, but the names are self-explanatory.

    Tool Count5/5

    With 5 tools, the server is well-scoped for a read-only academic workflow. Each tool covers a distinct, necessary aspect of the domain without unnecessary expansion.

    Completeness4/5

    The tool set covers the core read-only workflows: listing courses, assignments, upcoming/overdue filters, and grades. Minor gaps such as a single-assignment detail or course-specific grade breakdown are workaround-able and not critical to the stated purpose.

    Related MCP Connectors

    Related MCP Servers