Skip to main content
Glama

Camino MCP

A local, read-only Model Context Protocol (MCP) server for Santa Clara University's Camino (Canvas LMS). Ask a compatible local AI client about courses, assignments, upcoming/overdue work, and visible grade summaries. 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 only to https://camino.instructure.com/api/v1/. 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.

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. Create one in Camino → Account → Settings → Approved Integrations → New Access Token (if enabled by your institution); give it a short expiration and revoke it when unused. 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

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.

Related MCP server: Canvas MCP Server

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

For a private local MCP config that supports the standard mcpServers shape:

{
  "mcpServers": {
    "camino": {
      "type": "stdio",
      "command": "/absolute/path/to/uv",
      "args": ["run", "--locked", "--directory", "/absolute/path/to/camino-mcp", "camino-mcp"]
    }
  }
}

Provide the token to that client securely; desktop-launched apps often do not inherit shell exports. 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.

Tools and behavior

  • list_courses: merges paginated active, invited/pending, and favorite courses, deduplicated by numeric ID; unstarred courses stay included. Archived active enrollments may appear.

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

  • upcoming(days=7): scans every returned course, including pending/unstarred, for unsubmitted dated assignments within the next 1–31 rolling 24-hour days.

  • overdue: scans every returned course for past-due, unsubmitted dated assignments.

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

Cross-course scans fail explicitly if any course request fails; no partial result is labeled complete. Successful tool responses include "complete": true; errors include "complete": false. Assignment HTML/descriptions and arbitrary Canvas fields are excluded. Only Camino HTTPS links are emitted. Returned course names and assignment titles are untrusted data, not instructions. 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

  • The server allows only HTTPS requests to Camino's Canvas API; redirects are disabled and pagination is restricted to the same endpoint. Requests time out; 429 responses get two short retries; pagination is capped at 20 pages and fails rather than silently truncating results.

  • Read-only means no Canvas writes; any AI client granted these tools can still read and transmit the returned metadata. Use only a trusted client and handle student information under applicable institutional rules.

  • No live Camino account or real token was used in the automated tests. Canvas overrides, grades, permissions, missing enrollments, and institution-specific behavior need verification with a consenting user before relying on them for deadlines.

  • If your server returns an error, check your token, enrollment, or Camino availability. Do not paste tokens or full private tool responses into public bug reports.

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.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the burden of behavioral disclosure. It does disclose a key behavioral trait: results are shown only 'when visible to the token,' which is useful context about access scoping. However, it does not describe the return format, whether grades are aggregated or per-assignment, or any rate-limit/auth implications.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, compact sentence that front-loads the resource ('grade/score metadata') and adds the key scoping condition. Every word earns its place; no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless read tool, the description is mostly sufficient: an agent knows what it returns and the visibility caveat. However, with no output schema and no annotations, the agent is left guessing about the response shape (e.g., per-course objects, numeric scores, letter grades), which is a meaningful gap for a tool whose entire purpose is returning data.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so there is no schema to compensate for. The description adds meaning by specifying the scope ('by enrolled course') and the visibility condition, which is the only semantic content an agent needs for a parameterless call.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific resource ('grade/score metadata by enrolled course') and a condition ('when visible to the token'), which clearly distinguishes it from sibling tools like list_courses or list_assignments. It lacks a strong verb like 'retrieve' or 'list', but the noun phrase is specific enough to convey the tool's purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies a read-only lookup of grade metadata, and the sibling names (list_courses, list_assignments, upcoming, overdue) suggest it is the grade-specific counterpart. However, it does not explicitly state when to prefer this tool over alternatives or mention any exclusions, leaving the agent to infer usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_assignmentsB

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

ParametersJSON Schema
NameRequiredDescriptionDefault
bucketNo
course_idYes

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It discloses the key trait — this is a read operation ('Read') — but says nothing about what 'assignment metadata' includes, how the bucket filter behaves, pagination, or authorization requirements. The core safety profile is clear, but other behavioral details are absent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with the core action first and no filler. It is efficient, though the compressed jargon 'Canvas assignment bucket' trades clarity for brevity, and 'numeric' adds marginal value given course_id is typed as a string in the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 2-parameter tool with no output schema and no annotations, the description defines the basic call adequately. But it leaves bucket semantics undefined, doesn't characterize the return contents beyond 'metadata,' and fails to position the tool against upcoming/overdue, which may be overlapping views. Serviceable with clear gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It adds real meaning for course_id (identifies the course being read, expected to be numeric). But bucket is glossed as 'Canvas assignment bucket,' which largely restates the parameter name without explaining accepted values or filtering behavior — a significant gap given the schema provides no descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Read'), resource ('assignment metadata'), and scope ('one numeric course ID'), which distinguishes it from siblings like list_courses (course list) and upcoming/overdue (time-filtered views). However, 'optional Canvas assignment bucket' is cryptic — an agent cannot tell what a bucket is or what values it takes, so part of the intended behavior remains unclear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Read one numeric course ID's assignment metadata' implies when to use it — when you need assignments for a single course — and the sibling tool names provide some contrast. But the description never explicitly says when not to use it or names alternatives such as upcoming/overdue for time-filtered assignment views, so the guidance is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_coursesA

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

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral burden. It signals a read-only listing action and clarifies scope with 'including unstarred courses', but it does not mention authentication, pagination, or response shape. For a simple list tool this is acceptable, but there are still unstated behavioral details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, focused sentence with no filler. It front-loads the action and resource, then adds scope clarification. Every part of the sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list command with no output schema, the description is largely self-sufficient. It identifies the resource and scope. However, it could be more complete by noting whether pagination or authentication details apply, though these are not likely to block correct invocation for such a simple tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameterschers, so the baseline is 4. The description does not need to explain parameters; it adds useful context about what the returned list contains, which is sufficient given the empty input schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List'), names the exact resource ('courses'), and defines scope ('active, pending, and favorite') with the clarification that unstarred courses are included. This differentiates it clearly from sibling tools like list_assignments or grades.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool should be used when an agent needs the full set of courses, but it does not explicitly state when to choose it over alternatives or mention sibling tools. The context is clear enough for a zero-parameter listing tool, but the guidance is only implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

overdueB

Unsubmitted past-due assignments across all enrolled courses.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description carries the full burden. It reveals the scope ('across all enrolled courses') but does not clarify expected behavior such as whether it aggregates by course, whether it is read-only, or what the return structure looks like. For a simple lookup tool this is partially acceptable, but the absence of any behavioral detail is a gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with no wasted words, and the most important qualifiers ('unsubmitted', 'past-due', 'across all enrolled courses') are front-loaded. It is appropriately concise, though adding a verb would make it slightly more polished.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter tool with no output schema, the description conveys the essential information needed to decide whether to invoke it: the result is unsubmitted past-due assignments across all enrolled courses. It is simple enough that additional details like return format are not critical, though an explicit action verb would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the schema is fully covered by that absence. The description adds useful context by indicating the operation uses the implicit set of enrolled courses and requires no user-supplied arguments. This meets the baseline for a parameterless tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the resource: unsubmitted past-due assignments across all enrolled courses, which differentiates it from siblings like upcoming and list_assignments. It lacks an explicit verb such as 'list' or 'get', but the noun phrase and tool name make the intended action reasonably clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance is given about when to use this tool versus alternatives. The scope wording implies it is for overdue work rather than upcoming or all assignments, but the description does not state that or mention the sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

upcomingC

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

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNo

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full burden of explaining behavior. It states the filtering criteria but does not disclose whether results include due dates, how assignments are organized, whether only the count or full details are returned, or how the days parameter affects the range.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise and communicates the core selection criteria in a single sentence. It is front-loaded and easy to scan, though it omits parameter and return-format details that could have been included without much length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no annotationsasi and no output schema, the description must be self-sufficientam. It fails to explain the 'days' parameter, result format, default behavior, or how this tool compares to 'list_assignments' and 'overdue'. A simple listing tool still needs at least parameter and return-value context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is one parameter, 'days', with 0% schema description coverage. The description mentions a 1–31 day range but never explicitly maps this to the 'days' parameter or explains how changing it alters results. The parameter semantics are therefore largely left to inference.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies a specific resource—unsubmitted assignments—and a clear time window (next 1–31 days) across enrolled courses. It is distinguishable from siblings such as overdue and list_assignments, though it lacks an explicit verb like 'list' or 'get'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool (for future-due unsubmitted assignments) but provides no explicit guidance on when to choose it over list_assignments, overdue, or grades. It does not name alternatives or exclusion conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 5 tool updatesv0.1.0
    • First observedgrades
    • First observedlist_assignments
    • First observedlist_courses
    • First observedoverdue
    • First observedupcoming

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.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers