ScarletPlan
# ScarletPlan
Local-first Rutgers course planning assistant. Answers "what should I take and when?" using a CP-SAT solver, your real transcript, and live SOC data — running entirely on your machine, connected to Claude Desktop or Claude Code via MCP.
> **Disclaimer:** ScarletPlan is not an official Rutgers tool. Always verify plans with [Degree Navigator](https://degrenavigator.rutgers.edu) and your academic advisor.
---
## What it does
| Question | How |
|---|---|
| What courses am I eligible for? | Prereq tree evaluation against your transcript |
| Build me a conflict-free schedule | CP-SAT section optimizer with time/campus preferences |
| Plan my remaining semesters | CP-SAT degree planner against CS BS requirements |
| Will this section fill? | openSections fill-rate stats (grows over time) |
| Who's a good professor for 344? | Cached RateMyProfessors ratings with name matching |
---
## Setup (5 commands)
**Requirements:** Python 3.11+, [uv](https://docs.astral.sh/uv/), Claude Desktop or Claude Code.
```bash
# 1. Clone and install
git clone https://github.com/heetshah15/scarletplan && cd scarletplan
uv sync
# 2. Build the database (ingest current + next term for NB)
uv run python scripts/setup.py
# 3. Start the MCP server (test it works)
uv run scarletplan-server
# 4. Add to Claude Desktop config (see below)
# 5. Start the openSections poller cron (see below)
```
---
## Claude Desktop config
Add this to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"scarletplan": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/scarletplan", "scarletplan-server"],
"env": {
"SCARLETPLAN_DB": "/absolute/path/to/scarletplan/scarletplan.db"
}
}
}
}
```
Or see `docs/claude_desktop_config.snippet.json` for a ready-to-copy snippet.
---
## HTTP transport (website / remote clients)
The server also speaks MCP over streamable HTTP for the planned web frontend —
stateless with JSON responses, so multiple workers can run behind a load
balancer:
```bash
uv run scarletplan-server --transport streamable-http --host 127.0.0.1 --port 8765
# endpoint: POST http://127.0.0.1:8765/mcp
```
Configuration (flags override env vars):
| Env var | Flag | Default |
|---|---|---|
| `SCARLETPLAN_DB` | `--db` | `./scarletplan.db` |
| `SCARLETPLAN_TRANSPORT` | `--transport` | `stdio` |
| `SCARLETPLAN_HOST` / `SCARLETPLAN_PORT` | `--host` / `--port` | `127.0.0.1:8765` |
| `SCARLETPLAN_LOG_LEVEL` | `--log-level` | `INFO` |
| `SCARLETPLAN_REQUIREMENTS` | — | `requirements/cs_bs_sas.yaml` |
There is no auth on the HTTP transport: keep it bound to localhost and put the
website's authenticated backend in front of it. Every tool returns structured
JSON with `error`/`caveats[]` contracts (see `docs/PRODUCTION_AUDIT.md`), and a
`health` tool reports version, schema, and catalog freshness.
---
## Claude Code / Project Instructions
Paste this into your Claude project instructions (or `.claude/instructions.md`):
```
You are a Rutgers course planning assistant powered by ScarletPlan tools.
Rules:
- Always resolve course facts via tools, never from memory (SOC data changes).
- On first use: gather completed courses, target graduation, preferences via
set_user_profile so the student doesn't repeat themselves.
- Planning flow: get_requirements_progress → solve_degree_plan → present → iterate.
- Scheduling flow: solve_semester_schedule (k=3) → present tradeoffs →
validate_plan after any manual edits.
- Always surface caveats[] to the user, especially low-confidence ratings.
- End every degree plan with: "Verify this plan with Degree Navigator and your
academic advisor. ScarletPlan is not an official Rutgers tool."
- For professor ratings: always show match_confidence; flag anything below 85%.
```
---
## openSections poller (start now)
The fill-rate stats dataset only grows if the poller runs during registration windows.
Add this cron job so data starts accumulating:
```bash
# Edit crontab: crontab -e
*/5 * * * * cd /path/to/scarletplan && \
uv run python -m scarletplan.poller.poll_open \
--year 2026 --term 9 >> poller.log 2>&1
```
Key registration windows (when fill-rate data is most valuable):
- **November 2026** — spring 2027 registration
- **April 2027** — fall 2027 registration
- **January / September** — add/drop chaos
---
## RateMyProfessors ratings (optional)
RMP uses an unofficial GraphQL endpoint. Isolated and optional — if it breaks, all other tools continue working.
```bash
# Scrape once per semester, cache in DB
uv run python -m scarletplan.ingest.rmp.rmp_scraper --year 2026 --term 9
# Dry run to check match quality first
uv run python -m scarletplan.ingest.rmp.rmp_scraper --year 2026 --term 9 --dry-run
```
Match confidence ≥0.85 is reliable. 0.70–0.85 is surfaced as low-confidence. Below 0.70 is not stored.
---
## MCP tools
| Tool | What it does |
|---|---|
| `search_courses` | Full-text search the catalog |
| `get_course` | Full detail: prereqs, sections, core codes |
| `get_prereq_tree` | Prereq AST annotated with course titles |
| `check_eligibility` | Which courses you can take given your transcript |
| `get_sections` | Sections with meeting times, instructors, open status |
| `get_professor` | RMP rating + match confidence + courses they teach |
| `get_fill_stats` | Historical fill rate for a section index |
| `get_requirements_progress` | CS BS degree progress by bucket |
| `solve_semester_schedule` | Top-k conflict-free schedules with CP-SAT |
| `validate_plan` | Check a manually-edited schedule for conflicts |
| `solve_degree_plan` | Multi-semester degree plan with prereq ordering |
| `get_user_profile` / `set_user_profile` | Persistent student profile |
---
## Dev
```bash
uv run pytest # all tests
uv run pytest -m "not network" # skip live SOC tests
uv run python scripts/report_parse_failures.py # see unparsed prereq strings
```
Tests use synthetic in-memory SQLite — no network, no real DB required.
TDQS
Scored across 13 tools
Each tool targets a distinct aspect of course planning—eligibility, details, fill stats, professors, requirements, schedules—with clear descriptions that prevent confusion. The only potential overlap between solve_degree_plan and solve_semester_schedule is well-differentiated by their long-term vs. short-term focus.
All tool names follow a consistent verb_noun pattern in snake_case (e.g., get_course, solve_degree_plan). The verbs are appropriately chosen and uniform across the set, making it easy to predict functionality from the name.
With 13 tools, the number is well-scoped for a university course planning assistant. Each tool serves a clear purpose without redundancy, covering search, details, prerequisites, scheduling, and user profile management.
The tool set covers the full student planning workflow: searching courses, checking prerequisites and eligibility, managing schedules, validating plans, and storing preferences. No obvious gaps exist for typical planning tasks, though external actions like enrollment are excluded.