Developer Tools
upsked.com
Provides access to university course catalogs, sections, and availability data via the Upsked platform.
ENDPOINT 1
https://upsked.com/api/mcp
MCP server metadata
- Name
- upsked
- Version
- 1.0.4
Upsked is a college schedule planner with multi-school catalog support. Read-only catalog tools work without authentication. Schedule tools need auth (see AUTH). All times are in Philippine Standard Time (UTC+8), HH:MM format. Convert from the user's local timezone before time-based filters. **Multiple saved schedules (versioning) are fully supported.** The same user can keep several independent drafts per semester (e.g. Schedule A–E in the web UI). **Pass `version_id` on every schedule read/write and when applying planner output** so you target the right slot; see SCHEDULE VERSIONS below. Omitting `version_id` on `get_my_schedule` returns only the latest-edited draft, not a fixed letter. AUTH - Read-only catalog tools: no authentication. - Schedule read/write (get_my_schedule, all schedule mutations, build_optimal_schedule when saving): Authorization: Bearer <mcp_personal_access_token> (the `upsked_mcp_pat_v1_...` value from MCP client setup in Account settings), or an OAuth 2.1 access token from a connected MCP client (Supabase). Copied browser session JWTs work only if the server sets MCP_ALLOW_WEB_SESSION_JWT_FOR_MCP=true. **Always pass `version_id` when the user names Schedule A–E, wants a second draft, or has more than one saved plan** so reads and writes hit the intended slot. - Header-based anonymous MCP auth (X-Upsked-*) is removed. POST /api/auth/mintScheduleWriteToken is for the web app only (short-lived `schedule_write_token` in save request bodies—not an MCP header). SEMESTER - **Step 1:** Resolve `university_id` before catalog calls — user-stated school, **get_universities**, or **get_semesters** with `university`. Do not assume UPD when the user named another school. - If `semester_id` is missing or unclear, call **get_semesters** with the same `university` or read **upsked://semesters** (UPD-only when args empty). Omitting `university` on **get_semesters** returns **UP Diliman (upd)** semesters only — **REST GET /semesters without ?university= lists all schools instead.** Pass `university` for admu, upb, dlsu, etc. **Full policy:** resources/read `upsked://docs/multi-school`. TIMEZONE - All times are in Philippine Standard Time (UTC+8), HH:MM format. Convert from the user's local timezone before time-based filters. MCP RESOURCES (static guides — same idea as Figma MCP doc URIs: **resources/list** + **resources/read**) - `upsked://universities` — JSON: supported catalog schools (same shape as Public REST GET /universities). - `upsked://semesters` — JSON: semesters for one school + `default_semester_id` (defaults to **upd** when no args). - `upsked://docs/index` — Markdown: catalog of doc URIs + global conventions. - `upsked://docs/multi-school` — Markdown: **which school/semester when and why** (registry, `get_semesters` scoping, semester id shapes, UPD-only tools, public `/semesters` defaults). **Read this when the user names a school or pastes an unfamiliar semester id.** - `upsked://docs/planning-tools` — Markdown: **evaluate_schedule** vs **recommend_course_sections** vs **build_optimal_schedule**; **import_schedule** vs **search_courses**; rooms; saved schedule entry points. - `upsked://docs/schedule-versions` — Markdown: Schedule A–E / `version_id`, `get_my_schedule` behavior, **SCHEDULE DIVERSITY** across slots, auth. - Fetch these when tool descriptions are not enough or the user’s task spans multiple tools. SCHEDULE VERSIONS (Schedule A–E in the web app — use this whenever the user mentions plans A/B/C or “another draft”) - **You may and should use versioning.** Treat each `version_id` as a separate saved schedule for the same semester; operations on one do not erase others. - Each slot is a row in `user_schedules` keyed by `(semester_id, version_id)`. **Upsked exposes exactly five slots per semester:** `version_id` strings `"1"`–`"5"` (Schedule A–E in the web UI). Default display names: `"1"` → A, `"2"` → B, … `"5"` → E, unless the user renamed the version (`version_name`). - Tools that accept `version_id` (**pass it deliberately**): `get_my_schedule`, `add_section_to_schedule`, `remove_section_from_schedule`, `set_schedule_sections`, `add_sections_to_schedule`, `clear_schedule`, `swap_section`, `build_optimal_schedule` (always set `version_id` before `apply: true`). Async planner jobs, when your host exposes them, carry the same `version_id` in the job payload; applying the completed run updates that slot only. - `get_my_schedule` with `semester_id` omitted reads the caller's saved schedules across semesters/schools. With neither `version_id` nor `include_all_versions`, it returns only the single most recently updated saved version overall. Pass `semester_id` to scope to one semester, `version_id` to read a specific slot, or `include_all_versions: true` to list every matching saved version. If both `version_id` and `include_all_versions` are set, the query is still scoped to that `version_id` (you get at most one row). - There is no separate "create version" tool: the first write that **persists at least one section** for a **new** `version_id` (`set_schedule_sections`, `add_section_to_schedule`, `build_optimal_schedule` with `apply: true`, etc.) **inserts** that `user_schedules` row. Empty writes do not create a row. Other versions are untouched. - Planner dry-runs ignore saved drafts; persisting uses the `version_id` on `build_optimal_schedule` (`apply: true`) or the one bound to the async apply step for that run. SCHEDULE DIVERSITY (default when filling multiple slots A–E) - **Unless the user explicitly asks to copy the same plan to every slot** (“mirror”, “same on all versions”, “duplicate A to B–E”), **assume they want meaningfully different alternatives** across Schedule A–E (or any multiple `version_id`s). - `build_optimal_schedule` is **deterministic for fixed inputs**: same `course_ids`, semester, and flags → **one** optimal-feasible assignment. **`version_id` only chooses which row gets written**, not “give me another solution.” Calling it five times with identical args and `apply: true` on `"1"`…`"5"` **clones the same picks**—avoid that pattern when diversity is the goal. - **How to diversify:** (1) After a dry-run baseline, **vary** `prefer_morning` / `prefer_afternoon` / `prefer_friday_free`, `planning_mode`, day/time filters, or `vacant_windows` **per** `version_id` before persisting. (2) Persist the best plan to version `"1"`, then for each other slot call `recommend_course_sections` on that version’s current `section_ids` and use `swap_section` to take ranked alternatives for one or more courses (rotate which course you perturb so slots diverge). (3) If `get_my_schedule` with `include_all_versions: true` already shows different drafts, **extend those** instead of overwriting all slots with one composer run. ROUTING (three planning jobs + catalog; tool names are the registered MCP tool names) - (1) Analyze a known section_ids list: evaluate_schedule — primary. Returns conflicts, countable vs excluded units (PE/NSTP/CWTS/ROTC excluded from the 15-unit minimum), schedule spread, and draft_analysis (free windows, occupied days). It may widen the analyzed meeting footprint to linked block/common sections and exposes evaluated_section_ids + linked_block_section_ids when that happens. summarize_draft_schedule is a compatibility alias over the same engine; prefer evaluate_schedule for one payload. - (2) Rank sections for one course vs draft: recommend_course_sections — pass section_ids. Supports vacant_windows (hard/soft), strict_time_bounds with time_after/time_before, prefer_friday_free. Hard feasibility checks use each candidate's full meeting list plus block-linked section meetings (day/time filters only narrow which sections appear, not which meetings are validated). Defaults: open_only=true, avoid_conflicts=true. - (3) Multi-course composer: build_optimal_schedule — exact in-memory DFS over precomputed section bundles with bitset overlap checks; not greedy-by-request-order; **search is not parameterized by `version_id`** (see SCHEDULE DIVERSITY). apply defaults to false (dry-run). Set apply=true only to persist; requires auth when saving. **Pass `version_id` when persisting so picks land on Schedule A/B/… or another named slot, not only the last-edited draft.** Optional planning_mode: strict (force open_only+avoid_conflicts), balanced (use flags), salvage (allow closed sections and overlapping candidates). Returns unplanned_courses (with reason_code), underload, requested_min_countable_units (default 15), and unmet_planning_requirements when countable load is below min or courses could not be placed. planner_meta includes nodes_visited, search_budget_exhausted, search_status, planner_objective_score, objective_breakdown, decision_summary, planning_notes, candidate_widening_applied, relaxation_hints when unplanned. optimal_within_budget means the best schedule found before the node budget was exhausted. - Course discovery by keyword/code or GE/PE/NSTP browse: search_courses — not import_schedule. - User pasted CRS class codes (numeric strings): import_schedule — read-only resolver to section IDs; does not read or mutate the caller's saved Upsked schedule. - Full section list for one course_id: get_course_sections — raw catalog. - Saved schedule on the server: get_my_schedule — auth required. See SCHEDULE VERSIONS; pass version_id or include_all_versions when listing or targeting A–E. - Room name search (substring): search_rooms. Booked class meetings and optional derived free gaps: get_room_availability — include_free_slots defaults to true (larger payloads); set false if only booked rows are needed. - Replace all section IDs in one shot: set_schedule_sections. Swap one section on the saved version: swap_section (remove_section_id, add_section_id). MUTATIONS (all require auth; all accept optional `version_id` — **set `version_id` explicitly** when working with a specific Schedule A–E or a second draft) - add_section_to_schedule, remove_section_from_schedule, set_schedule_sections, add_sections_to_schedule, clear_schedule, swap_section — use swap_section instead of remove+add when replacing one section atomically. WORKFLOWS - Build from scratch: (1) build_optimal_schedule with course_ids and the target version_id (dry-run first, then apply=true to that version) — or — (2) clear_schedule on that version_id only, then recommend_course_sections per course, then set_schedule_sections with the final list and the same version_id. - Separate alternatives (e.g. Plan A vs Plan B): use version_id "1" vs "2"; do not rely on a single default row. **For several alternatives at once, follow SCHEDULE DIVERSITY**—do not repeat identical `build_optimal_schedule` applies across `version_id`s unless the user asked for the same plan everywhere. - Reschedule one course on the saved draft: swap_section (pass version_id for the slot).
Known tools 22
get_universitiesList supported catalog schools (university_id, label, status, capabilities).
Inferred read-onlysearch_coursesSearch Upsked catalog courses by code or keyword, with optional GE/PE/NSTP and open-only filters.
Inferred read-onlyget_course_sectionsGet sections, schedules, instructors, and block metadata for a course in a semester.
Inferred read-onlycheck_section_availabilityCheck slots_available, slots_total, demand, and overbooked status for one or more section IDs.
Inferred read-onlyevaluate_schedulePrimary schedule analyzer for a fixed section_ids list: echoes requested section_ids; conflicts; countable_units / excluded_units / gross_units; meets_minimum_countable_load; underload (countable below 15); min_countable_units_for_viable; schedule spread; draft_analysis (free windows, occupied days, conflict detail); primary_schedule_analyzer=true.
Inferred read-onlyadd_section_to_scheduleAdd a section to the caller's schedule version, or create a default version if none exists.
Potential side effectsremove_section_from_scheduleRemove a section from the caller's schedule version.
Potential side effectsset_schedule_sectionsReplace the caller's schedule version with the given section IDs atomically.
Inferred read-onlyadd_sections_to_scheduleAppend multiple sections to the caller's schedule version in a single atomic write.
Potential side effectsswap_sectionAtomically replace one section with another in the caller's schedule version.
Inferred read-onlyget_room_availabilityGet booked meetings for rooms in a semester, with optional free-slot computation.
Inferred read-onlyget_instructorGet instructor profile, ratings summary, taught courses, and matching sections for a semester.
Inferred read-onlyimport_scheduleResolve CRS class codes into Upsked section IDs, courses, and section details for a semester.
Inferred read-onlyget_course_section_changesRead recent NEW, REVEALED, CHANGED, DISSOLVED, and UNDISSOLVED events from the materialized changes feed.
Inferred read-onlylist_programsList UP Diliman (UPD) degree programs as JSON from the CRS programs protobuf—optional college and degree-type filters.
Inferred read-onlyrecommend_course_sectionsSearch and rank concrete section fits against the provided draft section IDs.
Inferred read-onlysummarize_draft_scheduleCompatibility alias: same engine as evaluate_schedule, returns draft-style fields plus academic_load and evaluate_schedule_cross_ref.
Inferred read-onlybuild_optimal_scheduleBounded MRV branch-search planner: top-K ranked bundles per course (not exhaustive catalog search).
Inferred read-onlyCONNECT WITH APPROVAL
Client installation
Review this server and its permissions before adding it. Secret placeholders must be set locally.
Codex
~/.codex/config.toml
[mcp_servers.upsked]
url = "https://upsked.com/api/mcp"
enabled = true
Claude Code
.mcp.json
{
"mcpServers": {
"upsked": {
"type": "http",
"url": "https://upsked.com/api/mcp"
}
}
}
Claude Desktop
Settings → Connectors → Add custom connector
Name: upsked
Remote MCP URL: https://upsked.com/api/mcp
Add this remote URL as a custom connector in Claude Desktop. Availability depends on the user plan and workspace policy.
Cursor
.cursor/mcp.json
{
"mcpServers": {
"upsked": {
"url": "https://upsked.com/api/mcp"
}
}
}
Visual Studio Code
.vscode/mcp.json
Add to Visual Studio Code{
"servers": {
"upsked": {
"type": "http",
"url": "https://upsked.com/api/mcp"
}
}
}
Generic MCP
Client-specific MCP configuration
{
"name": "upsked",
"transport": "streamable-http",
"url": "https://upsked.com/api/mcp"
}
MCP Inspector
Run the official MCP Inspector locally and enter the indexed Streamable HTTP endpoint.
TRUST AND VERIFICATION EVIDENCE
Trust Data Available
BuiltWith Trust API v2 evidence for upsked.com was fetched 2026-09-12T06:32:12.297Z.
upsked.com is assessed as Trusted: Domain has an established technology history spanning over a year.
Evidence is source-attributed and does not guarantee that a third-party server is safe. Risk labels are conservative metadata heuristics.