MCP server for querying NCCU course listings (qrysub.nccu.edu.tw)
Four tools with comprehensive descriptions (194 - 500+ chars each) and detailed parameter documentation. All tools have input schemas with type definitions. However, output schemas are documented only in descriptions, not as formal JSON Schema. Tool names follow verb_noun pattern (list_, search_, check_). Error handling is present but lacks recovery guidance. No tool annotations (readOnlyHint, destructiveHint). Descriptions are domain-specific and helpful but could be more concise for LLM parsing.
衝堂檢查(決定性計算,不用自己解析時間字串)。排課表的最後一步必用。 參數: semester: 學期碼,如 1151。 course_ids: 完整「9 碼」課號清單,如 ["000219541", "000359021"](6 碼查不到會報錯)。 extra_times: 額外時段字串,如 TA 實習課 ["四78"]、打工時段 ["五EFG"]。 回傳(dict): ok: True=完全不衝堂。注意:時間未定的課不在判斷範圍(見 warnings)。 conflicts: 衝突清單 [{a, b, overlap:[節次], cross_listed?}]。cross_listed=True 表示 兩門課同教師同教室同時段,多半是學碩合開同一堂課,不是真衝堂。 warnings: ["某課時間未定或無法解析,未納入衝堂判斷", ...]。 timetable: {週幾: {節次: 課名}} 週課表;TA 實習課節次標 "(實習)"。 courses: list(依 course_ids 順序),每項是該課的正規化資料(含 slots 與 note_facts;note_facts.ta_time 有值時已自動併入該課時段一起檢查)。 節次對照: 1=08:10 2=09:10 3=10:10 4=11:10 C=12:10 D=13:10 5=14:10 6=15:10 7=16:10 8=17:10 E=18:10 F=19:10 G=20:10(各 50 分鐘)。
列出政大開課單位代碼表(snapshot)。傳 query 以名稱子字串篩(如『財務』『通識』;用全名非簡稱)。 ★選課常識(先看): 大一大二全校共同必修(經濟學/統計學/初級會計學/微積分/大學英文…) 不掛在各系代碼下,而掛在「整開」科目代碼(課號 000 開頭);通識掛 2S1-2S8、體育必修 6S1、適應體育 6S3、輔系專班 3S1-3S8、學分學程 P01-P79。查系代碼找不到某門課時, 十之八九是它其實掛在這些共同單位下——改用 search_all(keyword=課名) 全校搜最快。 回傳型別是 list[dict](不是包在物件裡)。每筆: code(三碼,可含字母如 2S4/P53/ZU1)、 name(中文名)、level(大學部/研究所/學程/整開/通識/校級選修/體育課程…)、course_count。 code 可直接餵給 search_courses 或 search_all(dept=...);群組詞('通識'/'整開'/'體育'/ '學分學程'/'輔系')可直接餵給 search_all(dept=...) 一次查完整組。
全校跨單位彈性查課(伺服器端關鍵字搜尋,意圖查詢的主力工具)。 典型用法(條件全部 AND): search_all("1151", keyword="賽局") → 全校課名/教師/備註含「賽局」的課 search_all("1151", keyword="經濟學", week="3", language="中文") → 週三的中文經濟學課 search_all("1151", keyword="000219541") → 用完整 9 碼課號精準反查單門課 search_all("1151", teacher="郭力昕") → 這位老師全校開的所有課 search_all("1151", dept="通識", core_ge="是", week="2") → 週二的核心通識(8 類一次查) 參數: semester: 學期碼,如 1151 = 115學年第1學期。 keyword: 自由文字。伺服器端搜課名、教師名、備註、完整課號。 注意會命中「備註提到」的課(如備註寫先修經濟學),看 matched 欄位分辨。 week: '1'-'7'(週一~週日),伺服器端過濾。 language: '中文' 或 '英文',伺服器端過濾。 dept: 開課單位(代碼或中文名),或群組詞:'通識'(2S1-2S8)/'整開'/'體育'/ '學分學程'/'輔系',群組詞會自動展開成多個代碼一次查完。 kind: '必修'/'選修'/'群修',本地過濾(整開課此欄常為空,過濾會漏,慎用)。 core_ge: '是'=核心通識、'否'=一般通識。務必搭配 dept='通識'(或 2S1-2S8)使用: 非通識課的此欄位也是'否',不限單位會混入全校非通識課。 teacher: 教師名(含合開課),會自動兼作伺服器端關鍵字,可單獨使用。 keyword 與 dept 至少給一個(teacher 也算 keyword),否則報錯——無條件廣域查詢會被 伺服器 500 筆截斷,得到的是不完整的假象。 回傳 {count, truncated, warnings, courses:[...]}。truncated=True 表示伺服器端撈取命中 500 筆上限,本地過濾後的結果「不完整」,請加條件縮小再查。 每門課的欄位: course_id/name/teacher/time/slots(結構化節次)/credits(數字)/kind/target/ classroom/language/core_ge/note/note_facts/matched/remain_url/syllabus_url。 - matched: 這筆命中關鍵字的欄位(name/teacher/note/course_id),過濾雜訊用。 - note_facts 只在備註有料時出現,用 .get('note_facts', {}) 存取。內含: ta_time(實習課節次)/exam(會考日)/priority(優先/灌檔系所)/restriction(限修班級)/ no_add(不可加簽)/english_taught/has_ta_session(有實習課但時間未定)。 - target 是「開課對象」非選課資格;真正的資格限制看 note_facts.restriction/priority。 - 節次對照: 1=08:10 2=09:10 3=10:10 4=11:10 C=12:10 D=13:10 5=14:10 6=15:10 7=16:10 8=17:10 E=18:10 F=19:10 G=20:10(各 50 分鐘)。 選課常識(重要): 大一大二全校共同必修(經濟學/統計學/初級會計學/微積分/大學英文…) 不在各系代碼下,掛在「整開」科目代碼(dept='整開' 一次查、或 list_departments('整開')); 通識掛 2S1-2S8(dept='通識');體育必修 6S1、適應體育 6S3;輔系專班 3S1-3S8。 查不到課時先懷疑單位掛錯,改用 keyword 全校搜。
Output schemas not formally documented in JSON Schema format. Descriptions explain return structure in prose, but LLMs cannot parse field types/constraints from text alone. Formal schema enables downstream tool chaining and validation.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). All four tools are read-only, but this is not declared in the schema. Agents cannot infer safety properties without explicit hints.
Error messages in code (e.g., ValueError in _resolve_dept) are descriptive but lack recovery guidance. When a department is not found, the error suggests list_departments() but does not structure this as a recovery hint the LLM can act on programmatically.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 56 | <=2025-11-25 | v2 |
查某系所某學期的開課清單(即時查政大 API)。 參數: semester: 學期碼,格式『學年+學期』,如 1151 = 115學年第1學期、1142 = 114學年第2學期。 dept: 系所中文名或三碼代碼,如『財務管理學系』或『357』。用 list_departments 查代碼。 keyword: 選填。以關鍵字篩課名/教師/備註(如『交易』『個案』)。 回傳: {semester, dept_code, dept_name, count, courses:[...]}。每門課欄位同 search_all (course_id/name/teacher/time/slots/credits(數字)/kind/target/classroom/language/ core_ge/note/note_facts/remain_url/syllabus_url),note_facts 見 search_all 說明。 要跨單位搜、或不確定課掛哪個單位,用 search_all;本工具限單一單位。
search_all description is very long (500+ chars) and mixes usage examples with parameter documentation. Descriptions should be 50 - 200 chars for LLM parsing efficiency. Examples belong in separate documentation or tool tips, not the description field.
Parameter 'query' in list_departments and 'keyword' in search_courses/search_all accept free-form strings with no length limits or validation rules stated. Descriptions should specify max length and character constraints.