Anteater MCP
Anteater MCP is a zero-dependency MCP server that lets AI assistants help students pick classes at UC Irvine by wrapping the Anteater API's course catalogue, live schedule, grades, enrollment history, prerequisites, AP credit, and degree requirements.
Find classes: Search live sections for any term with times, instructors, rooms, seats, waitlists, and final exams; filter by department, GE, days, time windows, and availability.
Get recommendations: Rank courses by historical GPA while filtering on GE category, schedule constraints, and open seats.
Explore the catalogue: Search all courses, get full details (prerequisites, restrictions, GE credit, what it unlocks), and batch-compare up to 50 courses.
Judge classes and professors: Compare grade distributions by instructor or term, look up instructor profiles, view enrollment fill curves, and fetch past syllabi and textbooks.
Check eligibility: Evaluate prerequisite trees against completed courses and AP scores, and validate proposed schedules for time/final-exam conflicts, unit totals, and whether the set is actually enrollable.
Plan degrees: Pull program requirement trees, run deterministic degree-progress checks, list majors/minors/specializations, and view sample four-year plans.
Reference data: Read departments, terms, GE categories, and restriction codes directly as resources.
Guided workflows: 6 built-in prompts (plan-quarter, pick-professor, find-easy-ge, check-my-schedule, can-i-take, degree-check) drive multi-tool workflows.
Runs anywhere: MCP over stdio or streamable HTTP; works with Claude Desktop/Code, ChatGPT, Codex, and any MCP client.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Anteater MCPFind me a GE-2 for Fall that ends before 5pm and still has seats, ranked by how well people do."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Anteater MCP
An MCP server that lets Claude and ChatGPT help you pick classes at UC Irvine.
It wraps Anteater API — UCI's course catalogue, the live schedule of classes (WebSoc), historical grade distributions, enrollment history, prerequisite trees, AP credit and degree requirements — and exposes them as 19 tools, 6 guided prompts and 4 reference resources, shaped around the questions students actually ask.
Zero runtime dependencies. Run the source with Node 24 LTS, or download a standalone Linux, macOS or Windows executable that already contains the same Node runtime.
"Find me a GE-2 for Fall that ends before 5pm and still has seats, ranked by how well people do."
Course Title Units GPA A% n SeatsOpen Example meeting
------------ ------------------- ----- ---- --- ---- --------- ---------------------------
BIO SCI 17 EVO PSYCHOLOGY 4 3.80 88% 2410 2 TuTh 15:30-16:50 @ SH 134
UNI STU H30A ANALYSIS HEALTH LIT 4 3.77 84% 864 15 TuTh 12:30-13:50 @ ALP 1600
LPS 31 INTRO INDUCT LOGIC 4 3.61 80% 2108 11 TuTh 14:00-15:20 @ EH 1200Quickstart
git clone https://github.com/KKazuhaK/Anteater-MCP.git
cd anteater-mcp
node --version # Node 24 LTS
node anteater-mcp.mjs --list-tools # confirm it runsThen add it to your client — Claude Desktop, Claude Code, ChatGPT, or any other MCP client.
Nothing else is required. An API key is optional but recommended.
Related MCP server: Brown Courses MCP Server
Installing
Standalone binary
Each GitHub Release contains native
archives for Linux, macOS and Windows on amd64 and arm64, plus SHA256SUMS.txt. These do
not require Node.js:
# After downloading and extracting the archive for your platform:
./anteater-mcp --version
./anteater-mcp --list-toolsIn an MCP client configuration, use the absolute path to anteater-mcp (or
anteater-mcp.exe) as command and omit the args array. macOS archives are ad-hoc
signed; public Developer ID signing and notarization are not yet configured.
Docker
The published image supports Linux amd64 and arm64. Docker Desktop on macOS and Windows runs the same Linux image:
cp .env.example .env
# Set ANTEATER_MCP_TOKEN in .env, then:
docker compose up -d
curl -fsS http://127.0.0.1:8787/healthThe Compose service is non-root, read-only, capability-free and bound to loopback by default. See DEPLOY.md before placing it behind public HTTPS.
Claude Desktop
Open the config file:
OS | Path |
macOS |
|
Windows |
|
Linux |
|
Add an anteater entry. The path must be absolute — Claude Desktop does not run the
server from your project directory:
{
"mcpServers": {
"anteater": {
"command": "node",
"args": ["/absolute/path/to/anteater-mcp/anteater-mcp.mjs"]
}
}
}With an API key:
{
"mcpServers": {
"anteater": {
"command": "node",
"args": ["/absolute/path/to/anteater-mcp/anteater-mcp.mjs"],
"env": { "ANTEATER_API_KEY": "your-secret-key" }
}
}
}Restart Claude Desktop completely (quit, don't just close the window). You should see 19 anteater tools, and the 6 prompts appear as slash commands.
claude_desktop_config.example.json in this repo is the same thing, ready to copy.
Claude Code
claude mcp add anteater -- node /absolute/path/to/anteater-mcp/anteater-mcp.mjsWith a key:
claude mcp add anteater -e ANTEATER_API_KEY=your-secret-key -- node /absolute/path/to/anteater-mcp/anteater-mcp.mjsVerify with claude mcp list.
ChatGPT
Two routes. The first needs no server.
ChatGPT → Explore GPTs → Create → Configure → Create new action
Paste the contents of
gpt-actions-openapi.jsoninto the Schema boxAuthentication — two workable choices:
None. Anteater API is readable anonymously. Simplest, but you share a global hourly quota with every other anonymous caller and will hit 429s.
API Key → Auth Type: Bearer, with your Anteater API key. ChatGPT then sends
Authorization: Bearer <key>on every call and you get your own quota. ⚠️ The key is stored with the GPT, so anyone you share the GPT with uses your key. Fine for a private GPT; do not publish one with your key in it.
Paste
gpt-instructions.mdinto the Instructions box
The GPT calls anteaterapi.com directly. Twelve operations cover courses, WebSoc,
grades, enrollment history and degree requirements.
The trade-off: the GPT receives raw JSON. WebSoc responses nest four levels deep
(schools > departments > courses > sections), so broad queries get truncated by
Actions — the supplied instructions tell it to always narrow. Prerequisite evaluation
and conflict detection are not available; the model has to reason them out itself.
ChatGPT's Developer Mode connector needs a public HTTPS MCP endpoint:
node anteater-mcp.mjs --http --port 8787 # binds 127.0.0.1 only — do not add --host
# in another terminal
ngrok http 8787 # or: cloudflared tunnel --url http://localhost:8787Add the URL under Settings → Connectors → Advanced → Developer mode. All 19 tools work, including batch course lookup, deterministic degree-progress checks, prerequisite checking and conflict detection.
ChatGPT's developer mode supports OAuth, no authentication, or mixed — there is no field for a custom header, so put the token in the URL query string:
https://<your-domain>/mcp?token=<ANTEATER_MCP_TOKEN>This URL form is a compatibility option, not a security improvement: URLs may be saved in connector settings and reverse-proxy logs. Use a Bearer header whenever the client supports one.
Both transports ChatGPT accepts, SSE and streaming HTTP, are implemented. For a permanent deployment rather than a tunnel, follow DEPLOY.md — the setup is identical to the Claude one, only the connector UI differs.
⚠️ Without
ANTEATER_MCP_TOKENthe endpoint is unauthenticated. Set it before exposing anything. See HTTP mode security.
⚠️ ChatGPT's MCP plugins are web-only. OpenAI's own documentation says developer mode is "available to Pro, Plus, Business, Enterprise, and Education accounts on the web" — the phone apps cannot reach an MCP server. For ChatGPT on a phone, use a Custom GPT whose Action points at this server's REST facade, described below.
Which ChatGPT route gets you what
Custom GPT + Actions | Developer mode + MCP | |
Server needed | No | Yes, public HTTPS |
Auth options | None · API Key (Basic/Bearer/custom header) · OAuth | Access token / API key with a Bearer, Basic or custom header scheme · OAuth · none. Claude's connector dialog takes request headers too, so |
Can carry your Anteater key | Yes, API Key → Bearer | Yes, server-side via |
What the model gets | 12 raw API operations, JSON | All 19 tools, formatted, plus 6 prompts and 4 resources |
Prerequisite / conflict checking | No — the model must reason it out | Yes |
Works on mobile | Yes | No — MCP plugins are web-only |
On your phone
Claude's iOS and Android apps support remote MCP servers. Deploy this behind HTTPS, add it once on claude.ai in a browser, and it syncs to the apps — you cannot add a new server from the phone itself. DEPLOY.md has a complete recipe: token auth, a systemd unit, Caddy or nginx, and the connector setup.
The ChatGPT Custom GPT route also works on mobile and needs no server at all.
Codex
Codex speaks streamable HTTP and reads the token from an environment variable, so it never lands in a config file:
export ANTEATER_MCP_TOKEN=... # in your shell profile
codex mcp add anteater --url https://your.domain/mcp --bearer-token-env-var ANTEATER_MCP_TOKENOr write it to ~/.codex/config.toml directly — a project-local .codex/config.toml
takes precedence over the global one:
[mcp_servers.anteater]
url = "https://your.domain/mcp"
bearer_token_env_var = "ANTEATER_MCP_TOKEN"Codex reads the variable at connect time and sends Authorization: Bearer <token>.
Any other MCP client
The server speaks standard MCP over stdio. Point your client at:
command: node
args: ["/absolute/path/to/anteater-mcp/anteater-mcp.mjs"]Or run it as a streamable-HTTP server at http://127.0.0.1:8787/mcp with
node anteater-mcp.mjs --http.
Protocol versions 2025-06-18, 2025-03-26 and 2024-11-05 are all accepted;
the server negotiates down rather than echoing whatever it is sent.
What you get
Tools (19)
Finding classes
Tool | What it answers |
| The workhorse. Live sections for a term: times, instructor, room, seats, waitlist, final exam. Supports an exclusive day filter ( |
| The one you want. Filter by GE, days, time window and open seats; rank by historical GPA |
| What courses exist at all |
| One course in full: description, prerequisites, restrictions, what it unlocks |
| Up to 50 known courses in one compact comparison, with optional details |
| Which quarters have data, plus the academic calendar |
| Department codes ( |
Judging a class before you take it
Tool | What it answers |
| Grade distribution by instructor or by term — "which professor should I take?" |
| A professor's courses and the grades they actually give |
| Day-by-day fill curves — "will I get in?" |
| Links to syllabi from past offerings — real workload and grading breakdown |
| Required and recommended textbooks, with ISBNs and UCI Library links |
Checking you can actually enrol
Tool | What it answers |
| Walks the prerequisite tree against what you've completed |
| Meeting conflicts, final-exam conflicts, total units, and whether the set is actually enrollable — missing discussions/labs, cancelled or full sections, TBA meetings |
| What an AP score is worth: units, GE, courses cleared |
Planning a degree
Tool | What it answers |
| Degree requirement trees, including university-wide GE |
| Deterministic progress check from completed courses and AP scores; keeps uncertain rules visibly unverified |
| Majors, minors, specializations |
| The catalogue's recommended quarter-by-quarter sequence |
Five of these compute things the upstream API does not provide: prerequisite-tree evaluation, schedule conflict detection, the join between the live schedule and historical grade data, AP-grant rendering, and deterministic degree-progress evaluation.
All 19 are annotated readOnlyHint: true — nothing here mutates anything.
Prompts (6)
In Claude Desktop these appear as slash commands. Each one drives a full multi-tool workflow rather than a single lookup.
Prompt | Arguments | What it does |
|
| Builds a complete conflict-free schedule from scratch |
|
| Compares instructors by grades, then by who's actually teaching |
|
| Finds a GE that fits your schedule and grades well |
|
| Validates section codes for conflicts, units and enrollment risk |
|
| Checks eligibility, including AP substitutions |
|
| Runs the deterministic progress check, then plans what remains |
* = required. Arguments named term, ge, department, major and course offer
autocomplete through the MCP completions API.
Resources (4)
Reference tables your client can read directly, without spending a tool call:
anteater://reference/departments— every department code and nameanteater://reference/terms— every term with schedule dataanteater://reference/ge-categories— GE codes and what they meananteater://reference/restriction-codes— enrollment restriction codes, per the Registrar
Configuration
API key
Optional, but recommended: anonymous calls draw on a shared hourly quota that is easy to exhaust, and a key gives you your own.
It will not unlock fuzzy search. /v2/rest/search rejects ordinary keys with
not permitted to access this resource — it needs elevated permission ICSSC grants
separately. Without it search_courses falls back to substring matching on title, then
description, and says so in its output. The structured filters (department,
geCategory, courseLevel, units) are unaffected and are usually the better tool
anyway.
Choose type
secret—publishablekeys are verified against theOriginheader, which Node does not send, so they will not work hereEither set it in your client config (see above), or for local development:
cp .env.example .env # then edit .env
set -a; . ./.env; set +a # load it without echoing the value.env is gitignored. Never paste a key into an issue, PR or screenshot.
Environment variables
Variable | Purpose |
| Your secret key. See above. |
| Defaults to |
| HTTP mode only, and required before you expose the server. Clients send |
| HTTP mode only. Comma-separated extra origins to allow. |
| HTTP mode only. Which direct peers may set |
| HTTP mode only; equivalent to |
Command line
node anteater-mcp.mjs # stdio (what MCP clients use)
node anteater-mcp.mjs --http # HTTP on 127.0.0.1:8787, endpoint /mcp
node anteater-mcp.mjs --http --port 9000 # different port
node anteater-mcp.mjs --http --host 0.0.0.0 # bind all interfaces (warns; see below)
node anteater-mcp.mjs --list-tools # list every toolHTTP mode security
Binds
127.0.0.1by default.server.listen(port)with no host binds every interface, which would expose an unauthenticated server to the whole LAN.--hostis required to change that, and it warns when you do.Validates
Origin. The MCP specification requires this of local HTTP servers: without it, any page you visit can POST to your port and drive every tool (DNS rebinding / CSRF). Requests with noOrigin— native MCP clients — are allowed; requests with one must be localhost or listed inANTEATER_ALLOWED_ORIGINS.Access-Control-Allow-Originechoes the single validated origin, never*.Unauthenticated unless
ANTEATER_MCP_TOKENis set. That is fine on loopback and not fine anywhere else; the server warns at startup if it is bound off-loopback without one. See DEPLOY.md.HTTP activity is logged to stderr as one JSON request line and one response line. Logs include a request ID, method, sanitized target, remote address, status, duration, RPC/tool name, and outcome when available. Authorization values and RPC arguments are never logged; URL token values are shown as
[REDACTED]./healthreports status and the source URL;/sourceredirects to this repository, which helps anyone deploying a modified copy comply with AGPL section 13.
Troubleshooting
Symptom | Cause and fix |
Tools don't appear in Claude Desktop | The path must be absolute, and you must fully quit and reopen the app. Check the config parses: |
| The anonymous quota is shared and replenishes hourly. Set |
| Fuzzy search needs a privileged key that ordinary keys are not granted; it falls back to substring matching and says so. Use the structured filters instead. |
| A whole term is tens of thousands of sections. Add |
| UCI has three summer terms. Use |
| Use |
A course has no grade data | Recent quarters lag, and P/NP-only courses have none. |
Seats look stale | Live figures are cached for 5 minutes; the catalogue for 24 hours. |
Development
npm test # 20 conformance tests; makes no API calls
npm run test:live # live calls; needs a key in practice
npm ci # build tooling only; the shipped server has no runtime packages
npm run build:sea # standalone binary; requires the exact Node in .node-versionUPSTREAM.md records the exact Anteater API version and the upstream commits this server was validated against, endpoint by endpoint — start there when the API changes and something begins returning wrong or empty results.
VERIFICATION.md is a full release checklist — per-regression pass criteria, security checks and integration checks — written so someone who has never read the code can run it.
CI uses the same pinned Node 24 LTS release as Docker and native packaging. It runs the offline suite, syntax and OpenAPI checks, a standalone-executable smoke test, and a locked-down container protocol test. It deliberately makes no live Anteater API calls, so it never draws on the public rate limit.
Pushing a tag that exactly matches v plus the package.json version builds six native
executables, generates checksums and provenance attestations, pushes an amd64/arm64 image
to GHCR, and publishes the GitHub Release. Stable tags update :latest; every release
updates :beta; exact :vX.Y.Z tags are immutable.
After the first image publish, set the GHCR package visibility to Public once. The
workflow uses the scoped GITHUB_TOKEN; if repository policy blocks bot-created Releases,
add a fine-grained RELEASE_PAT secret with Contents write access, matching the upstream
project's fallback.
Scope
Anteater API also serves dining halls, library traffic and study-room bookings. Those are deliberately not wrapped — this server stays focused on choosing and registering for classes.
LARC tutoring sections are in scope but effectively dead upstream: /v2/rest/larc returns
22 courses for 2024 Fall and nothing for any term since, so a tool would always answer
"none" for the term a student is actually planning.
Known limitations
These are properties of the upstream data, not bugs. The server states them rather than papering over them, because the alternative is confident wrong advice.
WebSoc does not publish which discussion belongs to which lecture. Some courses encode it in the section number (
Lec A→Dis A1), others number companions independently (I&C SCI 31: lectures A/B, labs 1–9).check_scheduletherefore tells you when a required component is missing entirely, and when a pairing cannot be verified — but it cannot confirm that a given lab goes with a given lecture. Confirm that on WebReg. Neither of ICSSC's own clients infers this either: AntAlmanac and PeterPortal both render sections as a flat list and leave the pairing to the student, which is good evidence the data simply is not there.Enrollment restrictions are not evaluated against you.
search_sectionsandrecommend_coursessurface the codes and their meanings; whether you satisfy "Major only" or "Graduate only" is enforced by the registrar.Transfer and community-college coursework is absent.
check_prerequisitesreports any completed course it does not recognise instead of silently ignoring it, but only an advisor can clear transfer credit.No registration-window dates. The academic calendar covers instruction and finals; it does not say when your enrollment window opens. Check StudentAccess.
Grade data lags. Recent quarters may be missing, and a recent term's grades are often filed under
STAFF. A small sample size makes an average GPA unreliable — the tools always printnso you can judge.Historical GPA is course-wide.
recommend_coursesranks by the average across all past instructors, which may not be whoever is teaching this term. Useget_course_gradesto check the specific instructor before deciding.
Bugs found and fixed before release
A six-dimension parallel review (logic, MCP conformance, live-API contract, security, robustness, repo readiness) produced 41 raw findings, 38 after deduplication. The ones that would actually have misled someone:
Bug | Consequence |
A bare | Both transports. Over HTTP that was an unauthenticated 4-byte denial of service. |
Every final exam date was one month early | WebSoc's |
7 of 19 restriction codes were wrong |
|
| The bare |
Standalone lab courses counted as 0 units |
|
| Every seminar-only GE was invisible; GE-1A returned nothing at all. |
| The endpoint has a required |
HTTP mode bound | While logging "listening on localhost". |
Fall sorted as the earliest term of its year | Reversed the chronology in |
A second round, driving the server through six realistic student scenarios end to end, found 54 more — 10 of them blockers. The worst:
Bug | Consequence |
| It checked only times. A lecture with no required lab, or a full or cancelled section, passed silently — the student would be rejected at WebReg. |
| A student who could only attend Tu/Th was shown three- and four-day courses, and courses whose mandatory labs were all MWF. |
A bare instructor surname matched nothing |
|
Degree requirements defaulted to the 2023–2024 catalogue | Three years stale, with no indication, for a student on 2026–2027. |
| Then printed a confident "NOT satisfied" for work the student had actually done. |
| Its highest-ranked GE picks were courses the student could not enrol in. |
| When given the comma-separated string that |
Also fixed: inverted check marks in NOT prerequisite subtrees, course numbers lost for
the 48 department codes containing a space, multi-byte UTF-8 corrupted across HTTP chunk
boundaries, a quadratic-backtracking regex on unvalidated input, and socAvailable
mislabelled as "enrollment opens" when it is the schedule publication date.
API quirks worth knowing
Undocumented upstream; all handled here, and listed in case they save you the debugging.
daysmust be comma-separated.Tu,Thworks,TuThis rejected. It matches at least one of the listed days, not all of them.enrollmentHistoryreturns parallel arrays (dates[],totalEnrolledHistory[],requestedHistory[], …), not scalars.-1means "not tracked".finalExam.monthis 0-indexed.Course comments are raw HTML fragments, complete with
<p>and".startTime/endTimemean "starts at or after" and "ends at or before", not interval overlap./v2/rest/searchneeds a privileged API key. An ordinary key is refused withnot permitted to access this resource, which is a different error from thekey is requiredyou get with no key at all — worth distinguishing, since telling someone who already has a key to get a key is a dead end./v2/rest/websoc/syllabitakescourseId, notdepartment+courseNumber./v2/rest/courseMaterialsneedsdepartmentANDcourseNumbertogether. Either alone is refused, and it collapses the three summer sessions into a singleSummer.Restriction strings contain prose.
"A and N"must be split on whitespace and have the literaland/ordiscarded, or the conjunction renders as a code.Section status is an enum, not free text:
OPEN,Waitl,FULL,NewOnly, or empty. OnlyOPENmeans a continuing student can enrol now —NewOnlymarks seats held for incoming students.numNewOnlyReservedcounts seats inside the capacity that are reserved the same way, so the apparent opening overstates the real one.
Licence and attribution
Data from Anteater API, maintained by ICSSC Projects.
This is not an official UCI tool. Verify on WebReg or the General Catalogue before registering. Use is subject to Anteater API's attribution policy.
Licensed AGPL-3.0-or-later, matching the upstream Anteater API server so code can move freely in either direction if this is ever contributed upstream. This is an independent HTTP client and contains no upstream source code. If you modify it and run it as a network service, AGPL section 13 requires you to offer users your Corresponding Source — see NOTICE.
For academic use:
@misc{anteater-api,
author = {ICS Student Council},
title = {Anteater API},
year = {2024},
howpublished = {\url{https://github.com/icssc/anteater-api}},
}Available Tools
16 toolsap_creditWhat an AP exam is worth at UCIARead-onlyIdempotent
Look up what AP exam scores earn at UCI: units, elective units, GE categories and specific courses cleared. Use for incoming students planning a first quarter, or to work out whether an exam score already satisfies a prerequisite. The catalogueName in the output is the exact string check_prerequisites expects in apScores.
| Name | Required | Description | Default |
|---|---|---|---|
| exam | No | Exam name or part of one, e.g. "Calculus BC", "Computer Science". Omit to list all exams. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, covering safety. The description adds value by detailing what the output contains (units, elective units, GE categories, courses) and the catalogueName integration point, which is beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The primary purpose is front-loaded, followed by usage context and a precise integration hint. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only lookup with one optional parameter and no output schema, the description fully specifies the return content and how to use it with check_prerequisites. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single 'exam' parameter, and the schema description already explains the exam name/part and omit behavior. The tool description adds no extra parameter detail beyond what the schema provides, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('look up') and resource ('what AP exam scores earn at UCI') with concrete output components (units, GE categories, courses). It differentiates from sibling check_prerequisites by noting the output feeds that tool, so an agent can distinguish them.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives two explicit use cases: incoming students planning a first quarter and checking if an exam satisfies a prerequisite. It also explains how the output integrates with check_prerequisites. It doesn't explicitly state when not to use it, but the use cases are specific enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_prerequisitesCheck whether you can take a courseARead-onlyIdempotent
Evaluate a course's prerequisite tree against the courses a student has already completed, showing exactly which requirements are met and which are missing. Also reports enrollment restrictions (major-only, etc.), which the API cannot verify automatically.
| Name | Required | Description | Default |
|---|---|---|---|
| apScores | No | AP/exam scores keyed by exam name, e.g. {"AP CALCULUS BC": 5}. | |
| courseId | Yes | The course you want to take, e.g. "COMPSCI 161". | |
| completed | No | Courses already completed. Optionally append a grade after a colon, e.g. ["I&C SCI 46:B+", "MATH 2B:A-", "I&C SCI 6B"]. Without a grade, a minimum-grade requirement is reported as unverified. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this as read-only, non-destructive, and idempotent, so the safety profile is covered. The description adds useful behavioral context beyond annotations: it reports both satisfied and missing requirements, and it discloses the limitation that enrollment restrictions cannot be automatically verified by the API.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The primary evaluation behavior is front-loaded, and the additional enrollment-restriction note is concise and informative without being redundant with the schema or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only eligibility-check tool with fully documented parameters and safety annotations, the description covers the core behavior, scope, and a key limitation. There is no output schema, but the description gives enough about what is reported (met/missing requirements and restrictions) to guide an agent, though exact return structure is left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are fully documented in the schema. The description reinforces the role of 'completed' courses and mentions enrollment restrictions, but it does not add meaningful detail about apScores or the precise input formats beyond what the schema already provides. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Evaluate') and resource ('a course's prerequisite tree') and clearly states the output: which requirements are met and which are missing. It also adds a distinct second purpose, enrollment restrictions, making it easy to distinguish from sibling tools like get_course or course_grades.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context that this tool is for checking prerequisite and enrollment eligibility against a student's completed courses. It does not explicitly name alternative tools or state when not to use it, but the intended scenario is obvious and no misleading exclusions are present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_scheduleCheck a set of sections for conflictsARead-onlyIdempotent
Given a term and a list of 5-digit section codes, build the weekly timetable, total the units, and report any meeting-time or final-exam conflicts. Use this to validate a proposed schedule before registration.
| Name | Required | Description | Default |
|---|---|---|---|
| term | Yes | Required, e.g. "2026 Fall". | |
| sectionCodes | Yes | The 5-digit section codes to combine, e.g. ["34190","34191","30020"]. A comma-separated string is also accepted. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and non-destructive hints. The description adds specific behavioral context by stating it builds a weekly timetable, totals units, and detects meeting-time and final-exam conflicts. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the action and a clear use-case. No wasted words; every phrase contributes to understanding the tool's purpose and invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although there is no output schema, the description adequately explains expected outputs (timetable, unit total, conflict reports) and context (validation before registration). This covers the essential behavior for an agent to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents both parameters (term and sectionCodes) with examples and accepted formats, achieving 100% coverage. The description does not add extra parameter-level detail beyond what the schema provides, so baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: given a term and section codes, it builds a timetable, totals units, and reports conflicts. This distinguishes it from sibling tools like search_courses or find_sections by focusing on schedule validation rather than lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use this to validate a proposed schedule before registration.' It gives clear context but does not explicitly mention alternatives or when not to use it, though the purpose is distinct enough to infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
course_gradesGrade distribution for a courseARead-onlyIdempotent
Historical grade distributions and average GPA for a course, broken down by instructor (default) or by term. Use this to answer 'which professor should I take?' or 'how hard is this class?'. Data is from UCI's public records; recent quarters may be missing.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Restrict to a year, e.g. "2024". | |
| groupBy | No | How to break down the results. Default instructor. | |
| quarter | No | Restrict to a quarter. | |
| courseId | No | Course, e.g. "COMPSCI 161". | |
| department | No | Alternative to courseId: department code. | |
| excludePNP | No | Exclude Pass/No-Pass-only courses (default false). | |
| instructor | No | Restrict to one instructor (last name works). | |
| courseNumber | No | Alternative to courseId: course number. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already establish read-only, idempotent, non-destructive behavior. The description adds meaningful behavioral context: data comes from UCI public records, recent quarters may be missing, and results can be grouped by instructor or term. This goes beyond the structured metadata without contradicting it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences with no filler: the first states the resource, the second gives concrete use cases, and the third provides a relevant data caveat. Each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers purpose, grouping options, source, and recency limitations, which is strong for a read-only lookup tool with fully documented parameters. It does not describe the exact output shape, but since there is no required input and the schema documents all filters, this is a minor gap rather than a critical one.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds only marginal parameter context, such as highlighting the default grouping and connecting professor difficulty to the instructor/course filters. It does not substantially clarify parameters beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as providing historical grade distributions and average GPA for a course, with a default breakdown by instructor. It also distinguishes itself from sibling tools like enrollment_history or instructor_info by focusing on grade outcomes and professor difficulty.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use the tool: to answer 'which professor should I take?' or 'how hard is this class?'. It does not name alternatives or exclusions, but the use-case framing gives clear selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
enrollment_historyHow fast a class fills upARead-onlyIdempotent
Historical enrollment for a course: final enrollment vs capacity, waitlist size, and (for recent terms) the day-by-day fill curve. Use this to judge registration risk — 'will I get in?', 'do I need to enroll at 7am?', 'does the waitlist clear?'.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Restrict to a year, e.g. "2025". | |
| quarter | No | Restrict to a quarter. | |
| courseId | No | Course, e.g. "COMPSCI 161". | |
| showCurve | No | Show the day-by-day fill curve for the most recent term (default false). | |
| department | No | Alternative to courseId. | |
| instructor | No | Restrict to one instructor. | |
| sectionType | No | Restrict to a section type, e.g. Lec. | |
| courseNumber | No | Alternative to courseId. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so the description does not repeat these. It adds useful behavioral context: the data covers final enrollment, capacity, waitlist, and a fill curve for recent terms, plus the note that the fill curve is day-by-day. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with zero redundancy. The first sentence front-loads the data contents; the second sentence gives usage context with three crisp example questions. Every word earns its place, and the structure is immediately scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by naming the key return elements (final enrollment, capacity, waitlist, fill curve). It also explains the temporal scope ('for recent terms') and the intended use case. For an 8-parameter read-only tool, this is complete enough for an agent to decide whether to call it and interpret basic results.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, with each parameter (year, quarter, courseId, etc.) already explained. The description adds no parameter-specific detail beyond the general 'for a course', which is sufficient given the schema's thoroughness. Baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb-resource pair ('Historical enrollment for a course') and lists the exact data returned (final enrollment vs capacity, waitlist size, day-by-day fill curve). It distinguishes itself from siblings like course_grades and find_sections by focusing on enrollment trends and registration risk, making the tool's scope unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly explains when to use it: 'Use this to judge registration risk' and provides concrete example questions ('will I get in?', 'do I need to enroll at 7am?', 'does the waitlist clear?'). It does not name specific alternative tools or state when not to use it, but the context is clear enough that an agent can infer the appropriate scenario.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_sectionsFind class sections in a term (WebSoc)ARead-onlyIdempotent
The main course-finding tool. Queries UCI's live schedule of classes for one term and returns matching sections with meeting times, instructor, location, seats taken, waitlist and final exam. Filter by department, course number, GE category, instructor, days of week, time window, and seat availability. At least one narrowing filter besides the term is required.
| Name | Required | Description | Default |
|---|---|---|---|
| ge | No | Only courses satisfying this GE category. | |
| days | No | Section must meet on at least ONE of these days, e.g. "MWF", "TuTh", "M". See daysOnly. | |
| term | Yes | Required, e.g. "2026 Fall". | |
| limit | No | Max sections to return (default 60, max 300). | |
| units | No | Unit count, or "VAR" for variable-unit sections. | |
| avoidEnd | No | End of the blocked window, e.g. "18:00". Requires avoidDays. | |
| building | No | Building code, e.g. "ELH", "DBH". | |
| daysOnly | No | If true, `days` becomes exclusive: only sections that meet SOLELY on those days are returned. Use this for "I can only come to campus Tuesday and Thursday". | |
| division | No | Course level. | |
| avoidDays | No | Days of a window you must keep free, e.g. "M,W". Use with avoidStart/avoidEnd. | |
| endBefore | No | Section must end at or before this time, e.g. "17:00" or "5pm". | |
| avoidStart | No | Start of the blocked window, e.g. "13:00". Requires avoidDays. | |
| department | No | Department code or name, e.g. "COMPSCI", "CS". | |
| instructor | No | Instructor last name, e.g. "Shindler". | |
| startAfter | No | Section must start at or after this time, e.g. "10:00" or "10am". | |
| courseTitle | No | Substring of the course title. | |
| sectionType | No | Section type. | |
| availability | No | Seat availability filter. Default ANY. | |
| courseNumber | No | Course number, e.g. "161". | |
| sectionCodes | No | Comma-separated 5-digit codes or ranges, e.g. "34190,34200-34210". | |
| includeCancelled | No | Include cancelled sections (default false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint=false. The description goes beyond these by noting it queries the 'live schedule,' requiring at least one narrowing filter, and summarizing the returned section data. There is no contradiction between the description and the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact: three sentences convey what the tool does, what it returns, how it can be filtered, and the required-filter rule. Key information is front-loaded, and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 21 parameters and no output schema, the description handles selection context well by naming primary return fields and the mandatory narrowing constraint. Per-parameter semantics are fully covered by the schema, so this is a solid overall package. Minor gaps remain around pagination and output volume, but the schema's `limit` description partially addresses this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 21 parameters have schema descriptions, so the baseline is 3. The description names broad filter categories such as department, course number, GE, instructor, days, and time window, but it does not add detail beyond the schema, such as dependencies between avoidDays/avoidStart/avoidEnd or the default limit behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'The main course-finding tool' and states that it queries UCI's live schedule for a term and returns matching sections with meeting times, instructor, location, seats, waitlist, and final exam. This is a clear verb-resource pairing with a specific resource and scope. It does not explicitly contrast itself with sibling search_courses, so it is just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use it—finding course sections in a term—and explicitly states a hard precondition: 'At least one narrowing filter besides the term is required.' It also enumerates the dimensions an agent can filter by. However, it does not name alternative tools or state explicit when-not-to-use conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_courseGet full course detailsARead-onlyIdempotent
Full catalogue detail for one course: description, units, prerequisites (text and structure), courses that unlock from it, enrollment restrictions, GE credit, repeatability, and which terms it has been offered. Use this before advising someone to take a course.
| Name | Required | Description | Default |
|---|---|---|---|
| courseId | Yes | Course, e.g. "COMPSCI 161", "CS161", "I&C SCI 46". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds value by specifying the breadth of the returned data (e.g., prerequisite structure, enrollment restrictions, GE credit, repeatability, term offerings), which goes beyond the annotations and helps the agent understand what to expect from the response. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, well-structured sentence that front-loads the core purpose ('Full catalogue detail for one course') and then efficiently lists the included data categories. Every clause adds information without redundancy. It is concise yet comprehensive, with no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-course detail tool, the description enumerates all relevant content areas (description, units, prerequisites, unlockable courses, restrictions, GE credit, repeatability, terms offered). With no output schema, this description gives the agent a clear picture of what the tool returns. Combined with the annotations covering safety, the description is complete for correct invocation and expectation setting.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% (the only parameter courseId has a detailed description with examples like 'COMPSCI 161' or 'I&C SCI 46'). The description adds no further parameter guidance, but the schema already fully documents the parameter format. Baseline of 3 is appropriate because the description doesn't need to compensate for any schema gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states it provides 'Full catalogue detail for one course' and enumerates the specific data points (description, units, prerequisites, etc.). This clearly distinguishes it from sibling tools like search_courses (which searches across courses) and check_prerequisites (which only checks prerequisites). The verb 'get' and resource 'course' are specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear usage context: 'Use this before advising someone to take a course.' This tells the agent when to invoke this tool. It doesn't explicitly mention alternatives or when not to use it, but the context is sufficient given the sibling list and the tool's purpose as the comprehensive course detail source.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_program_requirementsGet degree requirementsARead-onlyIdempotent
The full requirement tree for a major, minor or specialization, or the university's general undergraduate requirements (GE categories, unit minimums). Use for degree planning — 'what do I still need?'.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Program kind. Default major. | |
| block | No | With kind="ugrad", which university-wide block to fetch. Default GE. | |
| programId | No | Program id from list_programs, e.g. "BS-201". Omit with kind="ugrad" for university-wide requirements. | |
| catalogYear | No | Catalog year, e.g. "20262027". Defaults to the one in effect today; pass the year you matriculated under if different. | |
| specializationId | No | Optional specialization id to include. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, openWorldHint=true, and destructiveHint=false, covering the safety profile. The description adds content scope (full requirement tree, GE categories, unit minimums) but does not elaborate on behavioral details like response size or the impact of catalogYear. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The core resource ('full requirement tree') is front-loaded, and the practical use case is stated concisely at the end.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only query tool with five well-described parameters and safety covered by annotations, the description adequately conveys purpose and usage. It does not explain output shape, but 'full requirement tree' hints at the structure, and no output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for all five parameters, including enum values and defaults. The description adds no parameter-specific meaning beyond what the schema already provides, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves the full requirement tree for majors, minors, specializations, and general undergraduate requirements. It distinguishes itself from siblings like list_programs by emphasizing the complete tree and degree-planning context, though it does not explicitly name an alternative.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Use for degree planning — what do I still need?' providing a clear when-to-use. It does not mention alternatives or exclusions, but the use case is specific enough to guide an agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_syllabiFind past syllabi for a courseARead-onlyIdempotent
Links to syllabi from previous offerings of a course, by term and instructor. Use to show a student what the workload, grading breakdown and topics actually look like before they enroll. Links point at UCI Canvas and may require a UCInetID login.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | Restrict to a year, e.g. "2025". | |
| quarter | No | Restrict to a quarter. | |
| courseId | Yes | Course, e.g. "COMPSCI 161". | |
| instructor | No | Restrict to an instructor, e.g. "SHINDLER, M.". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, and non-destructive behavior, so the bar is lower for the description. The description adds useful context beyond annotations: links point to UCI Canvas and may require a UCInetID login, which is important for setting expectations about access.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences each add value: the first defines behavior, the second gives the use case, and the third discloses the login requirement. Information is front-loaded with the core function, and there is no redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only retrieval tool with a fully described schema and safety annotations, the description covers the essential behavioral context, access implication, and motivating use case. It does not discuss alternatives, but that is a minor gap given the simplicity of the operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already covers all parameters with 100% description coverage, including examples for courseId, year, quarter, and instructor. The description's mention of 'by term and instructor' reinforces the main filter dimensions but does not add new semantic detail beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that this tool links to syllabi from previous offerings, scoped by course, term, and instructor. It also explains the practical purpose—showing workload, grading breakdown, and topics before enrollment—which effectively distinguishes it from other course-related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says when to use the tool: to show a student what a course is actually like before they enroll. It does not mention exclusions or alternatives, but the use case is specific enough to guide an agent without ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
instructor_infoLook up an instructorARead-onlyIdempotent
Find a UCI instructor and see their title, department, the courses they have taught, and their average GPA given across all courses. Use to evaluate a professor before enrolling.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Instructor name or part of it, e.g. "Shindler". | |
| ucinetid | No | Exact UCInetID if known. | |
| includeGrades | No | Also fetch grade distributions per course taught (default true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, non-destructive behavior. The description adds meaningful behavioral context by stating that it returns courses taught and an average GPA aggregated across all courses, which goes beyond the schema and helps the agent understand aggregation behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise sentences with no filler. The core action and output are front-loaded, and the use case is added in a single closing sentence. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich annotations, complete schema descriptions, and optional parameters, the description provides enough context for an agent to select and call the tool. It does not fully specify behavior when no parameters are supplied, but the schema's optionality and openWorldHint mitigate that gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description does not add meaning beyond the schema for parameters like name, ucinetid, and includeGrades, but it does imply the output context in which those parameters are used.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Find') and resource ('UCI instructor'), and enumerates the exact returned data points: title, department, courses taught, and average GPA. This clearly distinguishes it from sibling tools like course_grades, which focus on grades for a course rather than an instructor profile.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit use case: 'Use to evaluate a professor before enrolling.' It does not name alternative tools or state when not to use it, but the context is clear enough for an agent to select it over the listed siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_departmentsList department codesARead-onlyIdempotent
List UCI department codes used by the schedule of classes (e.g. COMPSCI, I&C SCI, BIO SCI). Use when you are unsure of the exact code for a subject. Optionally filter by a substring.
| Name | Required | Description | Default |
|---|---|---|---|
| filter | No | Optional substring to match against code or name, e.g. "computer". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, covering the safety profile. The description adds context about the data source (schedule of classes) and filtering behavior, which is useful. It doesn't describe return format or edge cases, but given the annotations cover the main safety aspects, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences: the first states purpose with examples, the second gives usage guidance and filtering. Every word earns its place, and the key information is front-loaded. No fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with one optional parameter and no output schema, the description covers purpose, usage context, and filtering. It doesn't mention what happens without a filter (returns all codes) but that is implied. The annotations cover safety, so the description is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the filter parameter is fully documented in the schema. The description only says 'Optionally filter by a substring', which largely repeats the schema's meaning. The description adds minimal extra value beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it lists UCI department codes used by the schedule of classes, with concrete examples (COMPSCI, I&C SCI, BIO SCI). This is a specific verb+resource and immediately distinguishes it from sibling tools like list_terms or list_programs, which handle different entities.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'Use when you are unsure of the exact code for a subject', which is a clear usage condition. It also notes optional substring filtering, providing practical guidance. However, it doesn't explicitly mention alternatives or when not to use it, so it's slightly below perfect.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_programsList majors, minors and specializationsARead-onlyIdempotent
List UCI degree programs. Use to find the program id needed by get_program_requirements.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | Which programs to list. Default majors. | |
| filter | No | Optional substring to match against the program name, e.g. "computer". |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint false, covering the safety profile. The description adds no additional behavioral details such as pagination or rate limits, but does not contradict the annotations. Given the rich annotations, a 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with a clear purpose, no redundancy, and the key information (what it lists and why to use it) is front-loaded. Perfectly concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple list tool with optional parameters and no output schema, the description is nearly sufficient. It states the purpose and ties to a downstream tool, though it could explicitly mention the return format (e.g., array of objects with id and name). This is a minor gap, but the tool is straightforward.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both parameters (kind and filter) described in the schema. The description does not add any extra meaning beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states the verb 'List' and the resource 'UCI degree programs', and explicitly mentions its purpose of finding the program id for get_program_requirements. This clearly distinguishes it from sibling tools like list_departments or list_terms.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides a clear use case ('Use to find the program id needed by get_program_requirements') and ties it to a specific sibling. It does not explicitly mention when not to use it, but the purpose is clear enough for the agent to select it appropriately.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_termsList terms and academic calendarARead-onlyIdempotent
List the UCI terms (quarters) that have schedule-of-classes data, plus the current week of instruction. Optionally pass a term to get that term's academic calendar (instruction begins/ends, finals week, holidays). Call this first when the user says 'next quarter' or doesn't name a term.
| Name | Required | Description | Default |
|---|---|---|---|
| term | No | Optional, e.g. "2026 Fall". If given, also returns that term's calendar dates. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey the read-only, idempotent, non-destructive profile. The description adds meaningful behavioral context beyond those annotations: it returns the current week of instruction, and with a term also returns academic calendar details such as instruction dates, finals week, and holidays.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: the first defines the core output, the second clarifies the optional behavior, and the third gives an explicit usage trigger. There is no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple optional-parameter read-only tool, the description is complete: it states the data scope, the optional calendar behavior, the calendar contents, and when to call it. The safety profile is covered by annotations, and the return shape is self-evident from the description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already fully documents the optional 'term' parameter, including a format example and the conditional calendar behavior. The description adds value by specifying what the calendar includes—instruction begins/ends, finals week, holidays—providing useful semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and resource ('UCI terms (quarters) that have schedule-of-classes data'), and adds the distinct secondary behavior of returning the current week and optional academic calendar. It is clearly differentiated from sibling tools like list_departments or search_courses.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit invocation trigger: 'Call this first when the user says "next quarter" or doesn't name a term.' It provides clear context for when to use the tool, though it does not name alternatives or state when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recommend_coursesRecommend courses matching constraintsARead-onlyIdempotent
The 'find me a class' tool. Combines the live schedule with historical grade data to rank candidate courses for a term. Filter by GE category, department, level, days of week, time window and seat availability; results are ranked by historical average GPA (or by open seats). Ideal for 'find me an easy GE-2 with open seats that doesn't meet before 10am'.
| Name | Required | Description | Default |
|---|---|---|---|
| ge | No | GE category to satisfy. | |
| days | No | Must meet on at least ONE of these days (not all), e.g. "TuTh". | |
| term | Yes | Required, e.g. "2026 Fall". | |
| limit | No | Max courses to return (default 20). | |
| minGPA | No | Only show courses whose historical average GPA is at least this. | |
| sortBy | No | Ranking. Default gpa. | |
| division | No | Course level. | |
| endBefore | No | Must end at or before, e.g. "5pm". | |
| department | No | Restrict to a department. | |
| startAfter | No | Must start at or after, e.g. "10am". | |
| availability | No | Seat filter. Default OpenOnly. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds valuable behavioral context by explaining that it combines live schedule data with historical grades and ranks by historical GPA or open seats, which goes beyond the structured hints. It does not describe edge cases or output format, but the key behavioral traits are disclosed without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is four sentences and every sentence contributes: the 'find me a class' hook, the data-combination mechanism, the filter and ranking behavior, and a realistic example. The opening tag is slightly redundant with the tool name, but it is short and immediately frames the tool's role. Overall it is tight and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 11 parameters and no output schema, the description supplies enough high-level context about what the tool does and how results are ordered. It does not detail the exact result shape, pagination, or data freshness caveats, but the phrase 'rank candidate courses' plus the example covers the agent's core decision needs. The rich annotations also carry part of the contextual burden.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter already carries its own meaning and examples. The description adds a high-level grouping of filters (GE category, department, level, days, time window, seat availability) and clarifies ranking options (GPA or open seats), but it does not add syntax or format details beyond the schema. This matches the baseline-3 expectation for fully documented parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb-resource pair: it 'rank[s] candidate courses' by combining live schedule data with historical grade data. It clearly differentiates itself from siblings like search_courses and course_grades by emphasizing the ranking and recommendation behavior, and the 'find me a class' tagline makes its purpose instantly recognizable. The example query reinforces the exact job this tool performs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a concrete ideal use case: "find me an easy GE-2 with open seats that doesn't meet before 10am". This tells an agent when the tool is appropriate for natural-language-style course recommendation. It does not explicitly name sibling tools or state when NOT to use it, so it stops short of full exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sample_programSample four-year plan for a majorARead-onlyIdempotent
The catalogue's recommended quarter-by-quarter course sequence for a major. Use to answer 'what should I take first year?' or to sanity-check whether a student is on track. Call with no argument to list the majors that have a published plan.
| Name | Required | Description | Default |
|---|---|---|---|
| program | No | Program name or id, e.g. "Computer Science", "computerscience_bs". Omit to list all. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds behavioral context by noting that calling with no argument lists majors with a published plan, which is a useful behavior beyond the schema. It doesn't contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each earning its place: what it is, when to use it, and how to invoke the no-argument behavior. The most important usage guidance is front-loaded. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, idempotent tool with a single optional parameter and no output schema, the description covers the essential usage context. It could mention what the returned plan looks like (e.g., quarters, course names), but the annotations and schema cover the safety and parameter aspects, so the gap is minor.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents the 'program' parameter with examples. The description adds the behavior of omitting the parameter to list all, which is a meaningful addition, but it doesn't add much beyond the schema's examples. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a catalogue-recommended quarter-by-quarter course sequence for a major, with a specific verb ('sample', 'recommended') and resource ('four-year plan'). It distinguishes itself from siblings like get_program_requirements and recommend_courses by focusing on the published plan. The title reinforces the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use it: to answer 'what should I take first year?' or to sanity-check whether a student is on track. It also gives a clear usage instruction: call with no argument to list majors with a published plan. This is strong guidance for an agent deciding between this and sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_coursesSearch the course catalogueARead-onlyIdempotent
Search the UCI course catalogue (all courses that exist, not term-specific offerings). Use a free-text query for fuzzy search ('machine learning', 'CS 161'), or the structured filters to browse (e.g. all GE-2 lower-division courses worth 4 units). To see which sections actually run in a given quarter and whether seats are open, use find_sections instead.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Max results (default 25, max 100). | |
| query | No | Free-text search over course titles, numbers and descriptions. | |
| maxUnits | No | Maximum units. | |
| minUnits | No | Minimum units. | |
| department | No | Department code or name, e.g. "COMPSCI", "CS", "Computer Science". | |
| geCategory | No | GE category the course must satisfy. | |
| courseLevel | No | Course level. | |
| courseNumber | No | Exact course number, e.g. "161", "45C". | |
| titleContains | No | Substring that must appear in the course title. | |
| descriptionContains | No | Substring that must appear in the course description. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering the safety profile. The description adds behavioral context beyond that: it clarifies the search covers the full catalogue rather than term-specific offerings, and gives example queries. It does not contradict annotations and adds useful scope information, though it omits details about return format or pagination.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with zero filler. It front-loads the primary purpose, then immediately gives usage guidance and the alternative tool. Every sentence earns its place, and the structure is logical and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 10 parameters, the description is complete in explaining the core behavior, usage modes, and the main alternative. It does not describe the return structure, but given the absence of an output schema and the read-only, idempotent nature, this is a minor gap. The description covers the essential context an agent needs to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so each parameter is documented. The description adds value by providing concrete usage examples ('machine learning', 'CS 161') and illustrating combined filters ('all GE-2 lower-division courses worth 4 units'), which clarify how to combine parameters beyond their individual definitions. This goes beyond the schema's isolated descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb 'search' and a clear resource 'UCI course catalogue', and explicitly clarifies the scope ('all courses that exist, not term-specific offerings'). It also distinguishes itself from find_sections, making its purpose unambiguous and differentiated from a key sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: it explains two usage modes (free-text query vs. structured filters) and gives a concrete alternative with a condition ('To see which sections actually run... use find_sections instead'). This leaves no ambiguity about when to select this tool over others.
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.
16 tool updates
v1.0.0- First observed
ap_credit - First observed
check_prerequisites - First observed
check_schedule - First observed
course_grades - First observed
enrollment_history - First observed
find_sections - First observed
get_course - First observed
get_program_requirements - First observed
get_syllabi - First observed
instructor_info - First observed
list_departments - First observed
list_programs - First observed
list_terms - First observed
recommend_courses - First observed
sample_program - First observed
search_courses
TDQS
Scored across 16 tools
Most tools target distinct resources and workflows; course lookup is split between catalogue search, live section search, and ranked recommendation, but descriptions explicitly steer usage. A few adjacent tools (course_grades vs instructor_info, sample_program vs get_program_requirements) could be confused in edge cases.
The dominant verb_noun pattern (list_, search_, get_, find_, check_, recommend_) is clear and predictable. Four noun_noun names (ap_credit, course_grades, instructor_info, enrollment_history) are minor deviations rather than a break in readability.
16 tools is at the high end, but each maps to a distinct aspect of UCI course planning: catalogue, sections, grades, instructors, prerequisites, schedules, syllabi, and degree requirements. It feels broad rather than padded, though a slightly leaner set might combine some grade/enrollment lookups.
For a read-only academic-advising server, the surface covers the main workflows: discovering programs/requirements, searching and validating courses, checking prerequisites and schedules, and evaluating instructors via grades and history. There are no obvious dead ends; list_programs and list_terms feed the tools that need IDs and terms.
Maintenance
Related MCP Connectors
Teamfight Tactics data & AI coaching for Claude and ChatGPT — 19 tools, built-in Riot key.
Search award flights and cash fares, optimize points, and predict fares inside ChatGPT and Claude.
Agent personas for Claude. 16 tools, 13 personas, 3 workflows. Zero extra API cost. Free.
Live SEO workflow tools for Claude Code, Codex, and AI agents.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables natural language queries about grades, GPA, attendance, and schedules by connecting Claude to StudentVue school dashboards. Includes analytical tools for grade simulation, what-if scenarios, and academic performance tracking based on live school data.19-
- FlicenseAqualityDmaintenanceEnables searching Brown University courses, getting detailed course info, and checking schedule conflicts via natural language, using the university's public course catalog API.5-
- FlicenseAqualityCmaintenanceLocal-first Rutgers course planning assistant that answers 'what should I take and when?' using a CP-SAT solver, real transcript data, and live SOC data, connected to Claude via MCP.13-
- FlicenseNot gradedqualityCmaintenanceProvides intelligent access to a university course catalog with full-text search, prerequisite tracking, instructor lookups, and course comparison prompts.-