錄:本地 AI 助手安全文件訪問(wèn) MCP Server 設(shè)計(jì))
大廠 MCP 面試實(shí)錄本地 AI 助手安全文件訪問(wèn) MCP Server 設(shè)計(jì)本文采用模擬面試形式復(fù)盤(pán)大廠 MCP 相關(guān)崗位面試中針對(duì)本地 AI 助手安全文件訪問(wèn)場(chǎng)景的考察邏輯與回答思路。面試官今天我們考察的是本地 AI 助手場(chǎng)景下的 MCP Server 設(shè)計(jì)。業(yè)務(wù)需求是為本地部署的 AI 助手開(kāi)發(fā)一個(gè)可安全訪問(wèn)用戶(hù)本地文件的 MCP Server傳輸層要求用 stdio你先說(shuō)說(shuō)整體的設(shè)計(jì)思路候選人首先基于 MCP 的客戶(hù)端-服務(wù)端架構(gòu)本地 AI 助手作為 Host內(nèi)置的 MCP Client 會(huì)啟動(dòng)本地的 MCP Server 子進(jìn)程通過(guò) stdio 傳輸層通信Server 從 stdin 讀取 JSON-RPC 消息向 stdout 返回響應(yīng)所有日志寫(xiě)入 stderr 避免破壞通信鏈路 [資料2]。能力設(shè)計(jì)上只讀的文件讀取操作適合封裝為 Resource通過(guò) URI 標(biāo)識(shí)文件路徑模型可直接讀取上下文寫(xiě)文件、刪除文件等有副作用的操作封裝為 Tool明確操作語(yǔ)義與參數(shù)約束。安全層面首先做路徑白名單限制只允許訪問(wèn)用戶(hù)指定的根目錄所有傳入路徑做標(biāo)準(zhǔn)化與遍歷校驗(yàn)同時(shí)把模型傳入的所有參數(shù)視為不可信輸入服務(wù)端獨(dú)立完成校驗(yàn)與權(quán)限判斷 [資料1]。面試官你提到讀文件用 Resource、寫(xiě)操作用 Tool為什么做這個(gè)區(qū)分如果我把所有文件操作都做成 Tool 是否可行候選人核心是語(yǔ)義匹配Resource 是只讀的上下文供給天然符合文件讀取的只讀屬性模型可通過(guò) URI 模板直接訪問(wèn)無(wú)需額外調(diào)用邏輯減少不必要的模型調(diào)用成本Tool 用于有副作用的操作能明確暴露操作的風(fēng)險(xiǎn)與參數(shù)約束符合 MCP 的能力分類(lèi)規(guī)范 [資料1]。全量做成 Tool 在功能上可行但存在兩個(gè)問(wèn)題一是讀操作每次都需要模型發(fā)起調(diào)用增加交互成本二是 Resource 的 URI 模板可做路徑前綴約束天然適配文件的層級(jí)結(jié)構(gòu)而 Tool 需要額外在參數(shù)里做路徑校驗(yàn)。但如果業(yè)務(wù)場(chǎng)景中讀文件也需要鑒權(quán)、脫敏那 Resource 就不合適了——因?yàn)?Resource 默認(rèn)不攜帶調(diào)用上下文無(wú)法關(guān)聯(lián)用戶(hù)身份此時(shí)讀操作也需要封裝為 Tool在參數(shù)中攜帶用戶(hù)標(biāo)識(shí)完成權(quán)限校驗(yàn)。面試官stdio 是本地子進(jìn)程通信如果 Server 進(jìn)程崩潰、或者傳輸中出現(xiàn)格式錯(cuò)誤的 JSON-RPC 消息Client 側(cè)需要做哪些處理你提到日志寫(xiě) stderr這里面有什么容易踩坑的地方候選人首先是異常處理邏輯Client 側(cè)需要監(jiān)聽(tīng) Server 子進(jìn)程的退出狀態(tài)非正常退出時(shí)要按退避策略自動(dòng)重啟避免頻繁重啟導(dǎo)致的資源雪崩針對(duì) JSON-RPC 消息因?yàn)?stdio 是換行分隔的消息流 [資料2]需要做消息分片處理避免緩沖區(qū)未收全完整消息就解析導(dǎo)致失敗遇到非法 JSON 時(shí)要返回對(duì)應(yīng)的 JSON-RPC 錯(cuò)誤響應(yīng)且不能將錯(cuò)誤內(nèi)容寫(xiě)入 stdout避免污染后續(xù)通信鏈路。關(guān)于 stderr 日志的坑點(diǎn)第一絕對(duì)不能往 stdout 寫(xiě)入任何非 JSON-RPC 內(nèi)容哪怕是一行調(diào)試 print 都會(huì)導(dǎo)致 Client 解析消息失敗這是 stdio 傳輸最常見(jiàn)的踩坑點(diǎn) [資料2]第二stderr 默認(rèn)是無(wú)緩沖的日志量過(guò)大會(huì)占用 IO 資源甚至占滿磁盤(pán)因此需要做日志級(jí)別控制生產(chǎn)環(huán)境僅保留 warn 及以上日志同時(shí)配置日志輪轉(zhuǎn)策略。另外還要注意stdio 傳輸默認(rèn)是同步請(qǐng)求-響應(yīng)模式長(zhǎng)耗時(shí)的文件讀取操作需要設(shè)置超時(shí)時(shí)間超時(shí)閾值應(yīng)根據(jù)業(yè)務(wù) SLA 與壓測(cè)結(jié)果確定超時(shí)后可以終止子進(jìn)程或返回錯(cuò)誤避免阻塞 Client。面試官現(xiàn)在用戶(hù)可能讓模型讀取敏感文件比如 /etc/passwd 或者用戶(hù)目錄外的文件你怎么防止路徑遍歷如果遇到幾個(gè) G 的大文件直接讀取全量?jī)?nèi)容傳輸會(huì)不會(huì)有問(wèn)題候選人路徑遍歷的防護(hù)需要做三層校驗(yàn)第一Server 啟動(dòng)時(shí)配置允許訪問(wèn)的根目錄比如用戶(hù)主目錄下的 Documents 文件夾所有傳入的文件路徑先通過(guò)標(biāo)準(zhǔn)化解析解析符號(hào)鏈接與..等相對(duì)路徑片段再校驗(yàn)標(biāo)準(zhǔn)化后的路徑是否在允許的根目錄下從根源上避免越權(quán)訪問(wèn)第二校驗(yàn)當(dāng)前進(jìn)程對(duì)目標(biāo)文件的讀權(quán)限避免讀取到無(wú)權(quán)限的系統(tǒng)文件第三參數(shù) schema 僅做結(jié)構(gòu)約束服務(wù)端必須獨(dú)立完成路徑校驗(yàn)不能信任模型傳入的路徑參數(shù) [資料1]。針對(duì)大文件場(chǎng)景不能直接讀取全量?jī)?nèi)容返回給模型否則會(huì)占滿上下文窗口??梢宰龇謮K讀取給讀文件 Tool 增加 offset、limit 參數(shù)每次返回合適大小的內(nèi)容片段由模型根據(jù)需求多次調(diào)用也可以結(jié)合 RAG 思路先對(duì)文件做切塊、索引模型調(diào)用時(shí)僅返回相關(guān)的語(yǔ)義片段同時(shí)保留來(lái)源元數(shù)據(jù)支持引用與排錯(cuò) [資料1]。舉個(gè)例子參考 MCP Python SDK 的公開(kāi)示例寫(xiě)法 [資料4]核心邏輯可以簡(jiǎn)化為偽代碼# 偽代碼文件讀取工具的核心實(shí)現(xiàn)邏輯 ALLOWED_ROOT Path.home() / Documents mcp.tool() def read_file(path: str, offset: int 0, limit: int 1024 * 1024) - str: # 路徑標(biāo)準(zhǔn)化與白名單校驗(yàn) target_path (ALLOWED_ROOT / path).resolve() if not str(target_path).startswith(str(ALLOWED_ROOT.resolve())): raise ValueError(訪問(wèn)的路徑超出允許范圍) if not target_path.exists() or not target_path.is_file(): raise ValueError(文件不存在或不是普通文件) # 分塊讀取避免占滿上下文 with open(target_path, r, encodingutf-8) as f: f.seek(offset) return f.read(limit)面試官stdio 是本地傳輸如果后續(xù)業(yè)務(wù)要支持多用戶(hù)并發(fā)訪問(wèn)或者要把 Server 部署到遠(yuǎn)程服務(wù)器你的方案有什么問(wèn)題怎么取舍候選人stdio 傳輸?shù)谋举|(zhì)是 Client 啟動(dòng)本機(jī)子進(jìn)程天然只支持單實(shí)例、本機(jī)訪問(wèn)無(wú)法支持多用戶(hù)并發(fā)也不適合遠(yuǎn)程部署。如果要支持多用戶(hù)或遠(yuǎn)程場(chǎng)景需要切換到 Streamable HTTP 傳輸此時(shí)需要補(bǔ)充一系列遠(yuǎn)程能力首先是認(rèn)證與授權(quán)每次請(qǐng)求都要校驗(yàn)用戶(hù)身份且要做細(xì)粒度的權(quán)限控制不能因?yàn)檎?qǐng)求來(lái)自 AI 應(yīng)用就默認(rèn)可信 [資料1]其次是會(huì)話管理、限流、超時(shí)控制避免單個(gè)用戶(hù)的請(qǐng)求占用過(guò)多資源還要做租戶(hù)隔離不同用戶(hù)的文件目錄互相隔離審計(jì)日志需要記錄用戶(hù)ID、調(diào)用的Tool、訪問(wèn)的資源范圍、結(jié)果狀態(tài)同時(shí)對(duì)敏感字段脫敏 [資料1]。但切換傳輸層的取舍也很明顯stdio 方案實(shí)現(xiàn)簡(jiǎn)單、延遲低、無(wú)需額外網(wǎng)絡(luò)配置適合本地單用戶(hù)場(chǎng)景Streamable HTTP 方案復(fù)雜度高需要處理網(wǎng)絡(luò)通信、安全、運(yùn)維等問(wèn)題適合多用戶(hù)、遠(yuǎn)程部署的場(chǎng)景本地場(chǎng)景下不需要過(guò)度設(shè)計(jì)。面試官你提到高風(fēng)險(xiǎn)操作需要用戶(hù)確認(rèn)這個(gè)確認(rèn)邏輯放在 Server 還是 Client 做如果模型試圖跳過(guò)確認(rèn)步驟直接執(zhí)行怎么處理候選人確認(rèn)邏輯必須放在 Server 端做因?yàn)?Server 是操作執(zhí)行方最清楚操作的風(fēng)險(xiǎn)。Server 在執(zhí)行寫(xiě)文件、刪除文件等高風(fēng)險(xiǎn)操作時(shí)先返回一個(gè)需要確認(rèn)的響應(yīng)明確告知操作的影響比如“將覆蓋 /home/user/docs/report.txt 的內(nèi)容是否繼續(xù)”Client 側(cè)收到確認(rèn)請(qǐng)求后彈出提示給用戶(hù)用戶(hù)確認(rèn)后再向 Server 發(fā)送執(zhí)行請(qǐng)求。如果模型跳過(guò)確認(rèn)步驟直接發(fā)送執(zhí)行請(qǐng)求Server 直接拒絕執(zhí)行必須等 Client 攜帶確認(rèn)標(biāo)識(shí)的請(qǐng)求才能繼續(xù)不能信任模型的調(diào)用流程。面試官點(diǎn)評(píng) -考察點(diǎn)MCP 核心架構(gòu)與三類(lèi)能力的語(yǔ)義區(qū)分、stdio 傳輸?shù)膮f(xié)議特性與邊界、安全防護(hù)設(shè)計(jì)、異常處理與可觀測(cè)性、方案擴(kuò)展性權(quán)衡。 -合格回答能明確 Resource 與 Tool 的適用場(chǎng)景知道 stdio 傳輸?shù)娜罩炯s束與消息格式要求能完成基礎(chǔ)的路徑遍歷防護(hù)理解參數(shù)校驗(yàn)必須由服務(wù)端執(zhí)行的原則。 -加分項(xiàng)能結(jié)合大文件場(chǎng)景設(shè)計(jì)分塊讀取/RAG 方案明確用戶(hù)確認(rèn)的落地方案能區(qū)分本地與遠(yuǎn)程場(chǎng)景的技術(shù)取舍考慮到審計(jì)日志的脫敏與子進(jìn)程生命周期管理對(duì) MCP 的安全邊界有清晰認(rèn)知??偨Y(jié)本地單用戶(hù)場(chǎng)景下基于 stdio 傳輸?shù)?MCP Server 實(shí)現(xiàn)成本低、延遲小核心是要守住安全邊界把模型輸入視為不可信輸入做好路徑校驗(yàn)、日志隔離、異常處理與用戶(hù)確認(rèn)流程。如果需要支持多用戶(hù)或遠(yuǎn)程訪問(wèn)再切換到 Streamable HTTP 傳輸補(bǔ)充認(rèn)證、授權(quán)、會(huì)話管理等能力避免過(guò)度設(shè)計(jì)。參考資料MCP 基礎(chǔ)知識(shí)stdio | https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdioMCP Protocol Overview and Schema | https://modelcontextprotocol.io/specification/2026-07-28/basic/transportsMCP Python SDK | https://github.com/modelcontextprotocol/python-sdk