A comprehensive MCP server for querying Stanford's course catalog, including the latest student course ratings.
Stanford MCP demonstrates solid definition quality with well-structured schemas and clear naming conventions. All 5 tools follow verb_noun patterns (list-, search-, get-). Descriptions are comprehensive and contextual, generally in the 100-300 character range, well above the 20-char minimum. Input schemas are complete with proper JSON Schema types, enums for constrained values (terms, ug_reqs, units, times, days, careers), and descriptions for all parameters. However, there are notable gaps: no output schemas are documented (critical for LLM understanding of return structure), error handling guidance is absent, and there are no tool annotations (readOnlyHint, idempotentHint) despite all tools being read-only. The descriptions mention output fields ('returns primary_class_id', 'returns short summary') but formal schema documentation is missing from the code.
Fetch a single course's full record by numeric course_id, including title, description, schedule/sections, GERS, attributes, tags, repeatability, and exam flags. The response surfaces `primary_class_id` (the main LEC section's class_id) at the top so you can render a course-card without parsing the nested `sections:` block. If you need render-ready data for several courses at once, prefer `get-courses` (plural) instead of calling this tool N times.
Batch-fetch multiple courses' summaries by numeric course_id, returning compact render-ready data (course_id, class_id, title, units, and clipped description per course). Faster and less verbose than calling get-course N times; use this when you want to render a course list. For full details on a single course, prefer get-course.
List departments (name and code) within a given school. If school is omitted, tool returns all departments across schools.
Return all schools available in ExploreCourses, optionally with department counts.
Search courses by free-text query and optional filters. Returns a short summary per match — each row includes course_id, the primary section's class_id (where available), units, title, and a clipped description. If the model wants to render a course-card or course-list, the class_id from this output is already sufficient; only call get-course / get-courses when deeper details are needed.
Output schemas completely undocumented. While input schemas are comprehensive, no formal schema for return values is visible in code. Description prose mentions fields (primary_class_id, sections, class_id, title, units, description) but LLMs cannot reliably parse unstructured text. For get-course and get-courses, the nested sections structure is referenced but not formally documented.
Tool annotations missing. All 5 tools are read-only, discovery, or safe operations, but none have readOnlyHint=true or idempotentHint=true. Per spec, these annotations guide agent safety assumptions and prevent unsafe retries of destructive operations.
Inferred effective spec: 2026-07-28+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 68 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 56 | - | v1 |
No error recovery guidance. Tool descriptions do not explain what the LLM should do if a search returns no results, a course_id is invalid, or optional filters produce empty sets. Pattern requires: 'If tool fails, try X' or 'Available alternatives: Y'. Currently agents must infer recovery paths.
Batch operation guidance incomplete. get-courses mentions 'Max 25 per batch' but does not specify what happens if the limit is exceeded (error? silent truncation?). search-courses does not document result limits or pagination strategy.
Parameter constraint clarity. The 'query' parameter in search-courses is required but has no length constraints, regex pattern, or minimum character guidance. LLMs may pass empty or single-character queries.