leave-copilot
Leave Copilot — 從 MCP 到專屬 Agentic 模型
一套可執行的參考實作:用 MCP 把一組刻意設計得很難的請假/差勤工具標準化,用 Google ADK 打造能操作它們的 Agent,用雙評測量出基座模型的不足,再微調出一個原生擅長操作這組工具的專屬模型。
這是 2026 iThome 鐵人賽 30 天系列的配套程式碼。
為什麼工具是「刻意設計得很難」的
一般設計 API 追求直觀易用,但這個專案需要相反的東西。
驗收的方式是比較微調前後的表現差異 —— 如果工具太直觀,基座模型本來就能正確呼叫,準確率一開始就接近滿分,微調自然展示不出任何提升。那不是因為微調沒效果,而是根本沒有可供改善的空間。
所以選擇標準只有一個:基座模型幾乎必錯,而微調可以教會。
四個刻意植入的難點
# | 難點 | 實作方式 | 模型的典型錯誤 |
① | 跨呼叫依賴 | 編號為不可推測的格式( | 跳過查詢,直接推測 |
② | Elicitation 三態 | 破壞性操作走 | decline 後改用其他工具繞道 |
③ | 狀態機約束 | 狀態只能 | 從 draft 直接跳到 approved |
④ | 參數陷阱 | 時數以小時計(半天 = 4 不是 0.5)、 | 傳 |
這四個難點的共同特徵:它們全部都是 JSON Schema 表達不了的規則。 Schema 管得住 status 必須是四個字串之一,但管不了「這個編號從哪裡來」。
Related MCP server: MCP Leave Management
快速開始
環境
套件 | 版本 | 為什麼 |
|
| 本系列使用 1.x 的 FastMCP,版本範圍不要省略 |
|
| 1.x 仍維護,但新專案沒理由從舊版開始 |
Python |
| 兩者的共同下限 |
第一項特別容易中招,因為 MCP Python SDK 官網預設顯示的是另一套 API 的文件(
MCPServer),與這裡使用的FastMCP寫法完全不同。
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt起 MCP Server
python -m mcp_server.server # streamable-http on 127.0.0.1:8090驗證四個難點
python eval/verify_difficulties.py會實際連上 Server,逐一觸發四個難點並檢查錯誤訊息與回傳語意:
難點 ① 跨呼叫依賴
✓ 捏造的編號被擋下
✓ 錯誤訊息指出正確取得方式
✓ search_leaves 查得到真實編號
…
難點 ④ 參數陷阱
✓ 餘額欄位以小時命名
✓ 傳姓名而非員工編號被擋下
難點 ② Elicitation 三態
✓ accept → cancelled
✓ decline → aborted
✓ cancel → aborted
✓ accept_but_false → aborted
✓ 撤銷後時數退回餘額
✓ decline 的訊息明確禁止繞道
✓ cancel 的訊息與 decline 語意不同
──────────────────────────────────────────────
19/19 通過重置測試資料
update_leave_status、cancel_approved_leave 會真的改變資料。每一輪評測開始前都必須重置,否則第二輪的前置條件跟第一輪不同,結果不可比。
python eval/reset.py工具集
九個工具,加上一個評測腳本專用的管理端點。
類別 | 工具 |
|
假單 |
| ✅ |
員工 |
| ✅ |
簽核 |
| ✗ |
交接 |
| ✗ |
撤銷 |
| ✗(走 Elicitation) |
管理 |
| ✗ |
readOnlyHint 不只是文件 —— 評測工具靠它計算「唯讀合規性」:Agent 有沒有在唯讀任務中動用寫入工具。
_reset_fixtures在 Agent 端必須用tool_filter排除掉。 一個叫「重置」的工具對 LLM 有莫名的吸引力。
為什麼錯誤訊息要寫這麼清楚
工具的錯誤訊息會原封不動回到模型手上,成為它下一步的依據。
# ✗ 模型只知道錯了,得猜哪裡錯
raise ValueError("Invalid status transition")
# ✓ 模型知道錯在哪、也知道該改成什麼
raise ValueError(
f"狀態不可從 {current} 跳至 {target},下一個合法狀態為 {next_valid}"
)這是用工具設計補償模型能力的典型手法,成本只是多寫幾個字。
專案結構
.
├── mcp_server/ # ✅ MCP Server:九個工具 + 四個難點
│ ├── server.py
│ ├── store.py # 模擬資料層
│ └── fixtures.py # 初始資料與 reset
├── eval/ # ✅ 驗證與重置腳本
│ ├── verify_difficulties.py # 19/19
│ ├── verify_agent.py # 架構驗證 10/10
│ └── reset.py
├── agents/leave_copilot/ # ✅ Google ADK Agent(含 elicitation callback)
├── plugins/ # ⏳ 軌跡記錄與生產防禦 Plugin
├── data/ # ⏳ 軌跡萃取與資料擴增
├── training/ # ⏳ SFT 訓練腳本
└── deploy/ # ⏳ 權重合併、量化、vLLM 部署✅ 已完成並實測 ⏳ 建置中
Port 分配
⚠️ FastMCP 與 Google ADK api_server 的預設 port 都是 8000,必須改掉其中一個。本專案把 MCP Server 移到 8090。
服務 | Port |
MCP Server(streamable-http) | 8090 |
Google ADK api_server | 8000 |
評測工具 Web UI | 8080 |
vLLM | 8001 |
Ollama | 11434 |
相關專案
ADEval — Google ADK Agent 評測工具(Apache-2.0)
Twinkle Eval — 標準 Benchmark 評測(MIT)
授權
Apache-2.0
已驗證的部分
eval/verify_difficulties.py 與 eval/verify_agent.py 都是實際跑過的,
不是「文件上這樣寫」。
MCP Server 層(eval/verify_difficulties.py) 19/19
四個難點的錯誤訊息、Elicitation 四條路徑
Google ADK 層(eval/verify_agent.py,A 段架構驗證) 10/10
McpToolset 載入、tool_filter 排除管理端點
accept / decline / cancel / accept-but-false 四條路徑
都確認走到 Client callback,且語意正確回報環境:mcp 1.29.1 + google-adk 2.7.1 + gemini-3.7-flash。
基座模型的行為觀察
verify_agent.py 的 B 段不做斷言,只記錄——模型答錯不代表測試失敗,
那正是要量的東西。實跑下來最值得注意的是這個失敗模式:
模型用文字回應代替工具呼叫。 面對破壞性操作,
gemini-3.7-flash傾向自己在對話裡問「你確定嗎?」,而不是呼叫cancel_approved_leave讓 Server 發出 Elicitation。結果是:確認流程從協定層掉回對話層, 而對話層的確認是沒有強制力的。
更嚴重的一個變體是幻覺型成功——模型回覆「我已將假單送出審核」,
但工具序列裡根本沒有 update_leave_status,假單狀態也沒變。使用者以為做完了。
這類失敗無法靠 Prompt 消除,因為它源自模型對「安全」的內建傾向。 這正是後續要用微調處理的東西。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Connect, monitor, and control AI agents — tasks, approvals, schedules, and governance.
Shared task queue for humans and AI agents: leases, handoffs, approvals and signed receipts.
Agentic workflow budget approvals with usage receipts.
The system of record for AI agent authority: playbooks, routed policy questions, reusable rules.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables employees to check leave balance, apply for leave, and view leave history through natural language using Claude Desktop.
- FlicenseNot gradedqualityCmaintenanceSimulates a leave management workflow for employees and managers, including leave application, balance checks, and approval processes.
- FlicenseBqualityCmaintenanceEnables HR teams to query and manage employee leave through natural language using Claude Desktop, with tools for checking balances, applying leave, and viewing history.3
- AlicenseAqualityCmaintenanceEnables LLM clients to handle leave applications by providing tools for initialization, organization selection, leave day calculation, attachment checks, uploads, and submission, with built-in business validation and environment switching.6MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/LiuYuWei/leave-copilot-agentic'
If you have feedback or need assistance with the MCP directory API, please join our Discord server