MCP / Plugin 實作

我為什麼自己建立 MCP 與 Plugin:從工具分散到真實驗收

三個 Agent 的能力與規則不同步,促使我建立共用 MCP 與外掛入口。記錄 OAuth 真實瀏覽器踩坑、459 次工具呼叫的失控探索,以及 0.4.2 的範圍修正與驗收數據。

實作紀錄期間:2026-08-03 至 2026-10-14

我開始建立 MCP,是因為一個很日常的問題:要查工時時,我想不起來哪個 Agent 會做。 有的工具只有 Claude Code 能用,Codex 沒有;Hermes 又有另一份操作方法。當三個 Agent 跨電腦使用,複製過去的 Skill 和 SOP 逐漸出現差異,修改一次並不代表每個入口都更新。

後來,需求延伸到個人知識庫與工作訊息:我希望在不同 AI 入口搜尋同一份資料,保留來源,也能限制哪些操作可以執行。這讓我同時處理 MCP 服務、Plugin 接入、OAuth、權限和驗收,而不只是寫出一個能回傳 JSON 的工具。

這篇整理我與 AI 開發工具協作的實作。需求、範圍與驗收取捨由我決定;程式修正、測試與排障由 AI 工具協作完成。數據是指定日期的歷史紀錄,不代表服務今天的即時狀態,也不是所有模型或外掛的通用表現。

起點:把能力與規則集中,減少每個入口各做一份

最初的能力中心把能力目錄、SOP、參數對照、核心執行與稽核放在共用服務。Agent 端保留薄的路由規則:先找到能力,再取得操作要求。改動核心行為時,盡量讓各入口共用同一份實作。

我對 MCP 和 Plugin 的分工,是從這個維護問題長出來的。

層級我放進去的責任原因
MCP 服務查詢、原文讀取、受限寫入、來源範圍與權限檢查不同 Agent 要取得一致的能力與結果
Plugin/connector讓特定平台發現服務、完成授權與載入工具各平台有自己的安裝與連線生命週期
Skill/使用規則何時呼叫、如何呈現來源、何時停下等使用者確認讓操作流程符合實際工作需求
Server 端強制檢查scope、允許的資料範圍、寫入預覽與執行約束使用規則不能代替真正的授權檢查

如果 Plugin 只把一個 search 轉呼叫成另一個 search,沒有增加平台接入或使用規則,我不會為了多一層包裝而建立它。私人知識庫能直接接 MCP,就直接接;需要特定平台入口時,再做相應的封裝。

哪些是自己建立,哪些是重用

實作自己處理的部分重用的部分
共用能力中心能力目錄、操作規則、核心執行與驗收流程既有業務系統 API
Vault RAG & Inbox MCPsearch/fetch、受限筆記寫入、OAuth 與來源政策接合既有 VaultRAG 檢索服務
Google Chat Reader 外掛外掛連線設定、OAuth 範圍、使用規則與實際讀取驗收Google 官方 remote MCP;沒有重寫 Google Chat 服務
DSH 接入自建 MCP 的桌面 OAuth 相容性、描述檔、問題修復與驗收第三方 dsh-mcp-connector 0.2.70;這個 connector 並非我開發

Google Chat 的例子尤其能說明取捨:既然已有可接入的官方服務,我做的是讓它進入自己的工作流程。當時選了 4 個 Chat 唯讀 scope,另加登入身分所需範圍。但「唯讀」只能限制操作種類,並不自動限制成指定工作群組;那次實作尚無群組白名單技術隔離。

2026-10-02 的外掛修正版能完成 search_conversations → list_messages,讀回訊息;同時,授權是否能在一小時後持續刷新,仍列為待驗收。修正版加入 access_type=offline 與 prompt=consent,並重新授權;Google 文件說明離線存取需在授權要求設定 access_type=offline,才能取得更新權杖。參數改對與長期運作通過,是兩項不同證據。 參考:Google OAuth 網路伺服器流程。

第一個實際故障:程式測試通過,瀏覽器 OAuth 卻失敗

2026-10-13,我把同一個 Vault MCP 接到 DSH。服務端先補上桌面 public client、PKCE 與受限制的 loopback callback。程式化探測已通過授權、search、fetch、refresh、revoke,真正的 Chrome 授權頁卻一直顯示「拒絕跨站請求」。

初期曾把方向放在批准碼錯誤或過期。後來追到服務端處理順序才發現:Origin 檢查發生在批准碼檢查之前。 請求根本還沒走到批准碼驗證。

同一授權頁的觀察修復前修復後
Referrer-Policyno-referrersame-origin
Chrome 表單 POST Originnull正確的同站 Origin
使用無效測試值送出403,拒絕跨站400,批准失敗或逾時
真實授權無法完成完成連線

上表的 400 不是授權成功;它表示請求已通過 Origin 檢查,進到預期的無效值驗證。之後另用真實流程完成授權,才算接通。

修正是調整這個服務授權頁的 Referrer-Policy,保留嚴格的同站檢查。這是本案瀏覽器與頁面設定的實測,不代表所有 OAuth 錯誤都應套同一修法。

為什麼先前測不到?因為 probe 自行帶了正確 Origin,繞過了瀏覽器實際產生標頭的那段行為。0.4.1 修復時,第一組 29 項測試通過;加入 Origin 回歸後,transport 組 11 項通過。兩組有重疊,不能相加成 40 項。

第二個實際故障:插件已安裝,host 還沒載入

另一個卡點發生在註冊設定。DSH 的 cordis.yml 是空清單佔位,註解指向 cordis.patch.yml;把條目寫進前者,套件雖然存在,工具仍不生效。後續修 patch 時,又曾用正規表示式改壞無關 YAML 區塊,必須還原再追加。

這次讓我把驗收拆成七關:安裝 → host 載入 → 描述檔匯入 → OAuth → search → fetch → 重啟後複測。每一關都要留下實際結果,不能靠模型說「完成」跨過下一關。

2026-10-13 最終驗收取得 1 個 server、7 個工具;實際 fetch 回 2,144 字元、103 行,has_more=false,帶來源路徑、雜湊與行號。重啟後不需重新授權,搜尋仍成功。這證明該次接入與重啟持久性,沒有涵蓋全部查詢品質或長期穩定性。

459 次工具呼叫,沒有換來等比例的進展

這次接入也留下不漂亮、但值得公開的數據。從安裝要求到重啟後複測,牆鐘約 6 小時 10 分鐘,包含人工介入、等待批准、停機與回合間隔,並非模型連續推理時間。

下面只統計當日 12:08 的第一份日誌快照,不是整場總量。

快照指標數值計算範圍
自安裝要求起的牆鐘時間4 小時 19 分 29 秒到第一份快照
工具呼叫459 次其中 pwsh 439 次
完全相同呼叫的額外重複152 次同組第一筆之外的重複
已完成上下文壓縮11 次該快照內
額外重複占工具呼叫約 33.1%152 ÷ 459,本文換算

約三分之一的呼叫是完全相同輸入的額外重複,但不能直接換算成三分之一時間可省:每次呼叫的執行與模型等待成本不同。日誌還顯示,後續至少 28 次同類瀏覽器歷史查詢,並沒有定位真正的 Origin 問題。

我後來把指導縮成有停止條件的關卡:同方法失敗兩次就交付證據;OAuth 只 connect 一次,逾時後查一次 status;不再反覆查歷史網址,也不讓 Agent 終止承載自己的主程序。限制流程之後,Agent 能停下來回報,但當時授權仍失敗。停止無效探索是改善流程,修復 Origin 才是解決故障。

這不是模型排名測試。當時模型標示為 strata-local/qwen3.8-flash-next-iq3_s,沒有固定任務換模型的對照組,因此無法把責任全部歸給模型、量化或 DSH。實際完成也有 Codex 修復與人工操作,不能宣稱 Agent 自主完成整段建置。

第三個實際故障:後端新增來源,MCP 還守著舊名單

2026-10-14,聯合搜尋出現 source_not_allowed。後端已擴大核准專案,但 MCP adapter 還寫死最初 4 個專案。候選結果一旦碰到新增專案,整次 search 就拋錯,連合法結果也不回傳。

這與 OAuth 是兩個不同問題。連線已成功,壞的是前後端重複保存的範圍政策。只改問某個舊專案會成功,也不能據此判斷其他搜尋全部正常。

0.4.2 將 adapter 的工作收斂為 ID 安全格式檢查;可查哪些專案由後端 published_projects() 決定。fetch 仍檢查 scope、search 登錄的不透明 ID、來源版本與核准範圍。部分候選不合法時保留有效結果,並回 coverage.partial 與 failures,讓呼叫端知道結果不完整。

2026-10-14 驗收實際結果可以支持的結論
adapter 回歸16 項通過覆蓋新來源、撤權後舊 ID、版本、分頁、惡意路徑與部分失敗等情境
Inbox 回歸26 項通過OAuth、安全、audit 與 transport 回歸通過
原本失敗的問句回 8 筆;partial=false,failures=[]該問句不再整批失敗
另一個限定來源問句回 7 筆,無部分失敗原有來源的一次回歸成功
精確 ID 查詢回 1 筆該議題可召回
原文 fetch5 個證據區塊、1,358 字元;has_more=false該來源可讀完
部署回執completed=true,rollback=false;health 版本 0.4.2該次正式部署通過

16 與 26 是這次兩組測試的項數,不能拿來當回答正確率。8 筆是該次搜尋結果數,不是完整資料總量。這次正式驗收使用 OAuth helper 與 connector 呼叫,沒有重新操作 DSH Desktop UI;不能借用前一天的 UI 驗收替代這一點。

給要做同類整合的人:先決定如何證明完成

這幾次實作之後,我會先把驗收表寫出來,再開始接線。下面是依本案整理的方法,並非另一輪已執行的測試結果。

要驗證的事留下的證據必須另外測的失敗情境
host 真的載入外掛可呼叫的工具清單與版本套件存在但未註冊、改錯 profile
使用者真的能授權真實瀏覽器表單、callback、連線狀態錯誤 Origin、過期 request、取消授權
查詢走對資料來源search 的來源類型與可 fetch 的 ID新增來源、來源撤權、部分候選失敗
回答能追溯fetch 的原文、行號或證據區塊、版本舊 ID、截斷內容、來源版本變動
寫入符合預期預覽內容、使用者確認、執行後回讀過期預覽、重複執行、未授權路徑
能持續使用重啟後實際查詢、到期後 refresh 測試憑證失效、服務中斷;各自記錄結果

對我而言,建立 MCP 和 Plugin 的成果,是讓原本分散的工作能力有共同入口,並能說清楚每個入口的權限、來源與失敗原因。這些事需要需求整理、架構取捨、實作和驗收一起做;工具數量只是其中很小的一部分。

數據來源與公開界線

本文依據三組自己的實作紀錄:2026-08-03 至 08-04 能力中心架構與執行紀錄、2026-10-01 至 10-02 Google Chat Reader 外掛設定與讀取紀錄、2026-10-13 至 10-14 DSH 軌跡分析與 MCP 0.4.1/0.4.2 部署驗收。量化數據來自日誌分析、測試結果與部署回執;公開稿已移除客戶名稱、內部單號、主機位置與憑證。

原始工作資料與 session 未公開,讀者無法由本文獨立重跑我的私人資料測試。本文提供的是明確的條件、結果與驗收方法,沒有宣稱節省多少人力、提高多少正確率或保證長期可用。Google 文件支持 OAuth 參數說明,並不替我的個案數據背書。

延伸閱讀:DSH 接本地 AI:工具能用之後,瓶頸才開始浮現。