共用基礎設施 & MCP Tool 輸出層¶
回到 資料流索引
共用基礎設施¶
safe_encode(data: Any) → str (toon_utils.py)¶
- 做了什麼:
- 偵測 Pydantic Model →
model_dump() json.dumps(default=str)序列化 datetime 等特殊型別- 呼叫
toon_format.encode()產出最終 TOON 字串
to_datetime(value) → datetime | None (time_tool.py)¶
- 做了什麼:統一處理多種輸入格式(ISO8601、
{dateTime:..}、{date:..}、UNIX timestamp)→ UTC+8 datetime
format_for_llm(dt) → str (time_tool.py)¶
- 做了什麼:將 datetime 格式化為
"YYYY-MM-DD HH:MM"(UTC+8),LLM 可直接理解
MCP Tool 輸出層¶
每個 MCP 工具最終回傳一個 TOON 字串 (str),由 safe_encode() 從 Python dict 轉換而成。
單一資料源工具¶
| MCP 工具 | 呼叫的轉換函數 | 最終回傳格式 |
|---|---|---|
get_all_calendar_events | to_toon_calendar() → safe_encode() | TOON 字串 |
get_event_from_calendar | to_toon_calendar() → safe_encode() | TOON 字串 |
get_all_tasks | to_toon_tasklist() → safe_encode() | TOON 字串 |
get_task_from_tasklist | to_toon_tasklist() → safe_encode() | TOON 字串 |
get_moodle_events | to_toon_moodle() → safe_encode() | TOON 字串 |
list_calendars | _list_writable_calendars() → safe_encode() | TOON 字串 ({calendars: [{id, summary, primary, accessRole}]}) |
list_tasklists | async_tasklists_list() → safe_encode() | TOON 字串 ({tasklists: [{id, title}]}) |
create_calendar_event | async_insert_event() → safe_encode() | TOON 字串 (API 回傳的 event dict) |
create_task | async_task_insert() → safe_encode() | TOON 字串 (API 回傳的 task dict) |
get_free_busy | async_query_free_busy() → safe_encode() | TOON 字串 (FreeBusy API 回傳原始結構) |
[!NOTE]
list_calendars和list_tasklists不使用 TOON 轉換函數(to_toon_*),而是直接在 Tool 層組裝 dict 後呼叫safe_encode()。 兩者的回傳結構不包含count欄位 — TOON 的key[N]語法已包含數量資訊。
複合工具¶
get_time_context → ResourceContextText¶
此工具整合三大資料源(Calendar + Tasks + Moodle),透過 ResourceContextText.from_resource_context() 轉換為統一 TOON 字串。
最終 TOON 字串的 dict 結構:
{
"meta": {
"time_range": {"start": "2026-01-01T00:00:00Z", "end": "2026-02-01T00:00:00Z"},
"generated_at": "2026-01-28T12:00:00",
"sources": ["google_tasks", "google_calendar", "moodle"]
},
"google_tasks": {
"Task List Name": {
"name": "...", "id": "...",
"parent_tree": {"父任務": {"子任務": "child"}},
"month": {
"2026-01": {
"done": [{"Task Title": {id, notes, done, done_at, due, p}}],
"pending": [...]
}
},
"undated": [...]
}
},
"google_calendar": {
"Calendar Name": {
"name": "...", "id": "...",
"location_index": {"臺科大 TR-510": "loc_1"},
"month": {
"2026-01": [{"Event Summary": {id, t:"10:00~11:00", d, l, r, all_day, recurrence}}]
}
}
},
"moodle": {
"course_index": [{"cid": "c1", "course": "[EE1001] 程式設計 張教授"}],
"semester": {
"114-1": {
"2025-11": {
"due": [{"title": "...", "cid": "c1", "status": "Closed", ...}]
}
}
}
}
}
launch_planner_studio¶
此工具呼叫 get_time_context 取得資料後,透過 build_planner_payload() 生成 Planner Studio 專用 payload,啟動本地網頁伺服器。最終回傳的是狀態摘要:
{
"ok": True,
"url": "http://localhost:PORT/sessions/SESSION_ID",
"opened_browser": True,
"session_id": "...",
"calendar_event_count": 42,
"task_count": 15,
"variant_count": 3,
"view_date": "2026-01-28",
"applied": False
}
錯誤回傳格式¶
所有工具在驗證失敗時回傳: - 認證失敗:"AUTH_REQUIRED: invalid_grant" 純字串 - Moodle 憑證缺失:safe_encode({"error": "Moodle credentials missing"}) TOON 字串 - 一般錯誤:由 @mcp_harden 裝飾器捕獲並格式化