MCP server: One MCP server.

Anteater MCP

@kkazuhakMCP server · External

UCI course search and registration planning: live sections, grades, prerequisites, conflicts.

Online coursesv1.0.0-beta.1AGPL-3.0JavaScript
Freeno charge per call

Runs on your machine from its package; the steps are below.

What it does

  1. Reads
  2. Writes
  3. High impact

At most: only reads or looks up information.

What it costs

Free

Odel charges nothing per call. The publisher may charge for its own service.

Runs locally over stdio

This server isn't hosted — your MCP client launches it from a package registry. Use one of the commands below, or drop the config into your client (e.g. Claude Desktop).

Dockerghcr.io/kkazuhak/anteater-mcp:v1.0.0-beta.1

Run

docker run -i --rm ghcr.io/kkazuhak/anteater-mcp:v1.0.0-beta.1

MCP client config

{
  "mcpServers": {
    "anteater-mcp": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "ghcr.io/kkazuhak/anteater-mcp:v1.0.0-beta.1"
      ]
    }
  }
}
README21 min read

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, degree requirements and supplementary RMP ratings — and exposes them as 20 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 1200

Quickstart

bash
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 runs

Then 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.


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:

bash
# After downloading and extracting the archive for your platform:
./anteater-mcp --version
./anteater-mcp --list-tools

In 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:

bash
cp .env.example .env
# Set ANTEATER_MCP_TOKEN in .env, then:
docker compose up -d
curl -fsS http://127.0.0.1:8787/health

The 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:

OSPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
Linux~/.config/Claude/claude_desktop_config.json

Add an anteater entry. The path must be absolute — Claude Desktop does not run the server from your project directory:

json
{
  "mcpServers": {
    "anteater": {
      "command": "node",
      "args": ["/absolute/path/to/anteater-mcp/anteater-mcp.mjs"]
    }
  }
}

With an API key:

json
{
  "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 20 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

bash
claude mcp add anteater -- node /absolute/path/to/anteater-mcp/anteater-mcp.mjs

With a key:

bash
claude mcp add anteater -e ANTEATER_API_KEY=your-secret-key -- node /absolute/path/to/anteater-mcp/anteater-mcp.mjs

Verify with claude mcp list.

ChatGPT

Two routes. The first needs no server.

A. Custom GPT with Actions — no hosting required
  1. ChatGPT → Explore GPTs → Create → Configure → Create new action
  2. Paste the contents of gpt-actions-openapi.json into the Schema box
  3. Authentication — 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.
  4. Paste gpt-instructions.md into 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.

B. Host the MCP server — full functionality

ChatGPT's Developer Mode connector needs a public HTTPS MCP endpoint:

bash
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:8787

Add the URL under Settings → Connectors → Advanced → Developer mode. All 20 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_TOKEN the 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 + ActionsDeveloper mode + MCP
Server neededNoYes, public HTTPS
Auth optionsNone · API Key (Basic/Bearer/custom header) · OAuthAccess token / API key with a Bearer, Basic or custom header scheme · OAuth · none. Claude's connector dialog takes request headers too, so ?token= is only a fallback
Can carry your Anteater keyYes, API Key → BearerYes, server-side via ANTEATER_API_KEY
What the model gets12 raw API operations, JSONAll 20 tools, formatted, plus 6 prompts and 4 resources
Prerequisite / conflict checkingNo — the model must reason it outYes
Works on mobileYesNo — 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:

bash
export ANTEATER_MCP_TOKEN=...   # in your shell profile
codex mcp add anteater --url https://your.domain/mcp --bearer-token-env-var ANTEATER_MCP_TOKEN

Or write it to ~/.codex/config.toml directly — a project-local .codex/config.toml takes precedence over the global one:

toml
[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 (20)

Finding classes

ToolWhat it answers
search_sectionsThe workhorse. Live sections for a term: times, instructor, room, seats, waitlist, final exam. Supports an exclusive day filter (daysOnly) and a blocked-window filter (avoidDays + avoidStart/avoidEnd) for "I work Monday afternoons"
recommend_coursesThe one you want. Filter by GE, days, time window and open seats; rank by historical GPA
search_coursesWhat courses exist at all
get_courseOne course in full: description, prerequisites, restrictions, what it unlocks
get_courses_batchUp to 50 known courses in one compact comparison, with optional details
list_termsWhich quarters have data, plus the academic calendar
list_departmentsDepartment codes (CS resolves to COMPSCI)

Judging a class before you take it

ToolWhat it answers
get_course_gradesGrade distribution by instructor or by term — "which professor should I take?"
get_instructorA professor's courses and the grades they actually give
get_rmp_ratingsRate My Professors average, review count and profile link for instructors teaching in a term
get_enrollment_historyDay-by-day fill curves — "will I get in?"
get_syllabiLinks to syllabi from past offerings — real workload and grading breakdown
get_course_materialsRequired and recommended textbooks, with ISBNs and UCI Library links

Checking you can actually enrol

ToolWhat it answers
check_prerequisitesWalks the prerequisite tree against what you've completed
check_scheduleMeeting conflicts, final-exam conflicts, total units, and whether the set is actually enrollable — missing discussions/labs, cancelled or full sections, TBA meetings
get_ap_creditWhat an AP score is worth: units, GE, courses cleared

Planning a degree

ToolWhat it answers
get_program_requirementsDegree requirement trees, including university-wide GE
check_degree_progressDeterministic progress check from completed courses and AP scores; keeps uncertain rules visibly unverified
list_programsMajors, minors, specializations
get_sample_programThe 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 20 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.

PromptArgumentsWhat it does
plan-quarterterm*, goalsBuilds a complete conflict-free schedule from scratch
pick-professorcourse*, termCompares instructors by grades, then by who's actually teaching
find-easy-geterm, ge, constraintsFinds a GE that fits your schedule and grades well
check-my-scheduleterm, sectionsValidates section codes for conflicts, units and enrollment risk
can-i-takecourse*, completedChecks eligibility, including AP substitutions
degree-checkmajor*, completed, apScoresRuns 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 name
  • anteater://reference/terms — every term with schedule data
  • anteater://reference/ge-categories — GE codes and what they mean
  • anteater://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.

  1. Go to dashboard.anteaterapi.com/create
  2. Choose type secret — publishable keys are verified against the Origin header, which Node does not send, so they will not work here
  3. Either set it in your client config (see above), or for local development:
bash
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

VariablePurpose
ANTEATER_API_KEYYour secret key. See above.
ANTEATER_API_BASEDefaults to https://anteaterapi.com. Point at a self-hosted instance.
ZOTCOURSE_API_BASEIndependent fallback for live WebSoc schedule queries. Defaults to https://zotcourse.appspot.com; set to off to disable. Only search_sections, check_schedule and recommend_courses use it, and fallback results are labelled as potentially cached.
ANTEATER_MCP_TOKENHTTP mode only, and required before you expose the server. Clients send Authorization: Bearer <token>, which is preferred, or use https://host/mcp?token=<token> where the client accepts only a URL. Any token in a URL can land in browser history, connector settings, and proxy logs. /health stays open. Unset means no authentication, which is only safe on loopback.
ANTEATER_ALLOWED_ORIGINSHTTP mode only. Comma-separated extra origins to allow.
ANTEATER_TRUSTED_PROXIESHTTP mode only. Which direct peers may set X-Forwarded-*. Accepts CIDRs, bare addresses, and the shorthands private and loopback. Unset means the headers are ignored, because they are client-supplied and would otherwise let anyone forge their address in your log. Behind a reverse proxy set this, or every request looks like it came from the proxy. private covers the Docker bridge.
HOST / PORTHTTP mode only; equivalent to --host / --port.

Command line

bash
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 tool

HTTP mode security

  • Binds 127.0.0.1 by default. server.listen(port) with no host binds every interface, which would expose an unauthenticated server to the whole LAN. --host is 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 no Origin — native MCP clients — are allowed; requests with one must be localhost or listed in ANTEATER_ALLOWED_ORIGINS.
  • Access-Control-Allow-Origin echoes the single validated origin, never *.
  • Unauthenticated unless ANTEATER_MCP_TOKEN is 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].
  • /health reports status and the source URL; /source redirects to this repository, which helps anyone deploying a modified copy comply with AGPL section 13.

Troubleshooting

SymptomCause and fix
Tools don't appear in Claude DesktopThe path must be absolute, and you must fully quit and reopen the app. Check the config parses: node -e "require('./claude_desktop_config.json')".
Anteater API rate limit hitThe anonymous quota is shared and replenishes hourly. Set ANTEATER_API_KEY.
search_courses returns odd resultsFuzzy 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.
Too broad from search_sectionsA whole term is tens of thousands of sections. Add department, courseNumber, ge, instructor or sectionCodes.
"2026 summer" is ambiguousUCI has three summer terms. Use Summer1, Summer2 or Summer10wk.
Unknown department "..."Use list_departments, or read anteater://reference/departments.
A course has no grade dataRecent quarters lag, and P/NP-only courses have none.
Seats look staleLive figures are cached for 5 minutes; the catalogue for 24 hours.
Schedule fallback appearsAnteater API was unavailable, so the schedule came from Zotcourse's WebSoc-backed endpoint. Verify seats and section pairing in WebReg. Set ZOTCOURSE_API_BASE=off if you do not want this network fallback.

Development

bash
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-version

UPSTREAM.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_schedule therefore 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_sections and recommend_courses surface 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_prerequisites reports 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 print n so you can judge.
  • Historical GPA is course-wide. recommend_courses ranks by the average across all past instructors, which may not be whoever is teaching this term. Use get_course_grades to 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:

BugConsequence
A bare null JSON-RPC message killed the processBoth transports. Over HTTP that was an unauthenticated 4-byte denial of service.
Every final exam date was one month earlyWebSoc's finalExam.month is 0-indexed (11 = December); the code treated it as 1-indexed. "Tue Nov 8" was really December 8 — someone books a flight on the wrong date.
7 of 19 restriction codes were wrongK was labelled "Cross-listed" but means Graduate only, and appears 608 times in a single term. X was "Separate final exam" but means authorization codes are needed even to drop.
"2026 Summer 1" silently returned SpringThe bare s alias swallowed summer. Three of six quarters were unreachable by natural phrasing, and it returned a confident, entirely wrong schedule.
Standalone lab courses counted as 0 unitscheck_schedule excluded Lab sections, so CHEM 1LD (3 units, no lecture) vanished — a student could misjudge the 12-unit full-time threshold that gates financial aid and F-1 status.
recommend_courses forced sectionType: LecEvery seminar-only GE was invisible; GE-1A returned nothing at all.
get_program_requirements with ugrad always failedThe endpoint has a required id parameter the tool never sent.
HTTP mode bound 0.0.0.0 without validating OriginWhile logging "listening on localhost".
Fall sorted as the earliest term of its yearReversed the chronology in get_enrollment_history and get_course_grades.

A second round, driving the server through six realistic student scenarios end to end, found 54 more — 10 of them blockers. The worst:

BugConsequence
check_schedule gave a clean all-clear to unenrollable schedulesIt checked only times. A lecture with no required lab, or a full or cancelled section, passed silently — the student would be rejected at WebReg.
days meant "meets on at least one of"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 nothingget_course_grades blamed the course — "may be new or graded P/NP only" — for a professor with 1,642 grades on record.
Degree requirements defaulted to the 2023–2024 catalogueThree years stale, with no indication, for a student on 2026–2027.
check_prerequisites silently dropped unrecognised coursesThen printed a confident "NOT satisfied" for work the student had actually done.
recommend_courses hid restriction codesIts highest-ranked GE picks were courses the student could not enrol in.
check_schedule threw a raw TypeErrorWhen given the comma-separated string that search_sections documents for the same parameter name.

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.

  • days must be comma-separated. Tu,Th works, TuTh is rejected. It matches at least one of the listed days, not all of them.
  • enrollmentHistory returns parallel arrays (dates[], totalEnrolledHistory[], requestedHistory[], …), not scalars. -1 means "not tracked".
  • finalExam.month is 0-indexed.
  • Course comments are raw HTML fragments, complete with <p> and &quot;.
  • startTime / endTime mean "starts at or after" and "ends at or before", not interval overlap.
  • /v2/rest/search needs a privileged API key. An ordinary key is refused with not permitted to access this resource, which is a different error from the key is required you 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/syllabi takes courseId, not department + courseNumber.
  • /v2/rest/courseMaterials needs department AND courseNumber together. Either alone is refused, and it collapses the three summer sessions into a single Summer.
  • Restriction strings contain prose. "A and N" must be split on whitespace and have the literal and/or discarded, or the conjunction renders as a code.
  • Section status is an enum, not free text: OPEN, Waitl, FULL, NewOnly, or empty. Only OPEN means a continuing student can enrol now — NewOnly marks seats held for incoming students. numNewOnlyReserved counts seats inside the capacity that are reserved the same way, so the apparent opening overstates the real one.

Distribution

Published to the MCP Registry as io.github.KKazuhaK/anteater-mcp, listing the container image only. The registry entry describes how to run your own instance; it does not point at anyone's deployment, since a hosted instance is gated behind its own token and its upstream quota belongs to whoever runs it.

Each release also publishes the GHCR image and standalone binaries for six platforms.

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:

bibtex
@misc{anteater-api,
  author = {ICS Student Council},
  title = {Anteater API},
  year = {2024},
  howpublished = {\url{https://github.com/icssc/anteater-api}},
}

Similar modules

Browse Online courses