議架構(gòu)全鏈路拆解:從設(shè)計(jì)原理到工程實(shí)踐)
1. MCP 架構(gòu)概覽從協(xié)議設(shè)計(jì)到落地實(shí)踐的全鏈路拆解第一次接觸 MCP 是在一個(gè)內(nèi)部工具鏈整合的項(xiàng)目里當(dāng)時(shí)團(tuán)隊(duì)有七八個(gè)自研系統(tǒng)每個(gè)系統(tǒng)都有自己的數(shù)據(jù)接口和調(diào)用規(guī)范光是維護(hù)這些接口的適配層就耗掉了將近兩個(gè)人力。后來有人提了一句“要不試試 MCP”我才開始認(rèn)真研究這套協(xié)議。MCP 全稱 Model Context Protocol翻譯過來叫模型上下文協(xié)議本質(zhì)上是一套讓 AI 模型與外部工具、數(shù)據(jù)源之間進(jìn)行標(biāo)準(zhǔn)化通信的協(xié)議規(guī)范。它要解決的問題很直接過去每接一個(gè)新工具就要寫一套適配代碼現(xiàn)在只要工具實(shí)現(xiàn)了 MCP Server任何支持 MCP 的客戶端都能直接調(diào)用。這套協(xié)議的核心價(jià)值在于“解耦”。打個(gè)比方以前的模式像是每個(gè)電器都配一個(gè)專用插座換一個(gè)電器就得換一次墻上的面板MCP 做的事情就是統(tǒng)一了插座標(biāo)準(zhǔn)不管是燈、風(fēng)扇還是充電器插上去就能用。對(duì)于做 AI 應(yīng)用開發(fā)的團(tuán)隊(duì)來說這意味著工具集成從“一對(duì)一硬編碼”變成了“一對(duì)多標(biāo)準(zhǔn)化接入”工程效率的提升是數(shù)量級(jí)的。這篇文章適合幾類人看一是正在做 AI Agent 工具鏈整合的開發(fā)者二是想了解 MCP 協(xié)議底層機(jī)制的技術(shù)負(fù)責(zé)人三是已經(jīng)用過 MCP 但對(duì)其架構(gòu)設(shè)計(jì)還不太清楚的中級(jí)工程師。我會(huì)從協(xié)議的整體設(shè)計(jì)思路講起然后逐層拆解核心通信機(jī)制、SDK 選型、STDIO 傳輸模式最后給出實(shí)操步驟和踩坑記錄。內(nèi)容偏工程實(shí)踐不會(huì)停留在概念層面。2. 協(xié)議整體設(shè)計(jì)與核心思路拆解2.1 為什么需要 MCP從碎片化集成到標(biāo)準(zhǔn)化協(xié)議在沒有 MCP 之前AI 應(yīng)用接入外部工具的方式基本是三種第一種是直接在代碼里寫死 API 調(diào)用比如你要讓模型查數(shù)據(jù)庫就在業(yè)務(wù)邏輯里硬編碼一段 SQL 查詢第二種是寫插件系統(tǒng)每個(gè)工具按照自定義規(guī)范實(shí)現(xiàn)一個(gè)插件接口第三種是用 Function Calling把工具描述塞進(jìn)模型的上下文里讓模型自己決定調(diào)用哪個(gè)。這三種方式各有各的問題。硬編碼的維護(hù)成本極高工具一多代碼就變成一團(tuán)亂麻自定義插件系統(tǒng)雖然好一些但每個(gè)平臺(tái)的插件規(guī)范不一樣換個(gè)框架就得重寫Function Calling 看起來優(yōu)雅但工具數(shù)量一多光是工具描述就占滿了上下文窗口而且模型對(duì)工具的理解能力也有上限。MCP 的思路是把“工具提供方”和“工具調(diào)用方”徹底分開。工具提供方只需要實(shí)現(xiàn)一個(gè) MCP Server按照協(xié)議規(guī)范暴露自己的能力調(diào)用方只需要實(shí)現(xiàn)一個(gè) MCP Client按照協(xié)議規(guī)范發(fā)起請(qǐng)求。雙方通過 JSON-RPC 進(jìn)行通信協(xié)議層負(fù)責(zé)處理能力協(xié)商、消息路由、錯(cuò)誤傳遞這些通用邏輯。這樣一來工具開發(fā)者不用關(guān)心誰來調(diào)用應(yīng)用開發(fā)者不用關(guān)心工具怎么實(shí)現(xiàn)各司其職。注意MCP 不是要取代 Function Calling兩者是互補(bǔ)關(guān)系。Function Calling 解決的是“模型如何決定調(diào)用哪個(gè)工具”的問題MCP 解決的是“工具如何標(biāo)準(zhǔn)化接入”的問題。實(shí)際項(xiàng)目中經(jīng)常是兩者配合使用。2.2 核心架構(gòu)分層Client、Server 與 Transport 的三角關(guān)系MCP 的架構(gòu)可以分成三層來看。最上層是Client 層負(fù)責(zé)與 AI 模型交互把模型的意圖翻譯成 MCP 協(xié)議消息中間是協(xié)議層定義了消息格式、能力協(xié)商規(guī)則、生命周期管理最下層是Transport 層負(fù)責(zé)實(shí)際的網(wǎng)絡(luò)通信目前支持 STDIO 和 HTTP 兩種傳輸方式。Client 和 Server 之間的通信遵循嚴(yán)格的握手流程。連接建立后Client 先發(fā)送initialize請(qǐng)求攜帶自己支持的協(xié)議版本和能力列表Server 收到后返回自己的能力列表和版本信息雙方確認(rèn)無誤后Client 發(fā)送initialized通知握手完成。這個(gè)過程很像 TLS 握手目的是確保雙方對(duì)協(xié)議版本和能力集有共識(shí)避免后續(xù)通信出現(xiàn)不兼容的情況。Transport 層的選擇直接影響部署方式。STDIO 模式下Client 和 Server 運(yùn)行在同一臺(tái)機(jī)器上通過標(biāo)準(zhǔn)輸入輸出進(jìn)行通信適合本地工具集成HTTP 模式下Server 可以部署在遠(yuǎn)程通過 HTTP 請(qǐng)求通信適合云端服務(wù)。兩種模式各有適用場景后面會(huì)詳細(xì)展開。2.3 能力協(xié)商機(jī)制讓 Client 和 Server 互相“摸底”能力協(xié)商是 MCP 協(xié)議里設(shè)計(jì)得比較巧妙的一個(gè)環(huán)節(jié)。每個(gè) MCP Server 在握手階段會(huì)聲明自己支持哪些能力比如tools工具調(diào)用、resources資源讀取、prompts提示模板。Client 根據(jù)自己的需求決定是否使用這些能力。舉個(gè)例子假設(shè)你有一個(gè) MCP Server 提供了數(shù)據(jù)庫查詢工具和文件讀取資源。Client 在握手時(shí)看到 Server 聲明了tools和resources兩個(gè)能力就可以在后續(xù)交互中分別調(diào)用tools/list獲取工具列表或者調(diào)用resources/list獲取資源列表。如果 Client 本身不支持resources能力那它可以選擇忽略這部分聲明只使用tools。這種設(shè)計(jì)的優(yōu)勢在于向前兼容。新版本的 Server 可以聲明新能力老版本的 Client 不認(rèn)識(shí)這些能力就直接忽略不會(huì)導(dǎo)致連接失敗。反過來也一樣新 Client 連接老 Server 時(shí)只使用老 Server 聲明支持的能力即可。3. 核心通信機(jī)制與 JSON-RPC 實(shí)操解析3.1 JSON-RPC 2.0 在 MCP 中的具體應(yīng)用MCP 的通信協(xié)議基于 JSON-RPC 2.0這是一套輕量級(jí)的遠(yuǎn)程調(diào)用規(guī)范。每條消息都是一個(gè) JSON 對(duì)象包含jsonrpc、method、params、id這幾個(gè)字段。請(qǐng)求消息有id響應(yīng)消息也有對(duì)應(yīng)的id通過這個(gè)字段做請(qǐng)求-響應(yīng)匹配。一個(gè)典型的工具調(diào)用請(qǐng)求長這樣{ jsonrpc: 2.0, id: 1, method: tools/call, params: { name: query_database, arguments: { sql: SELECT * FROM users LIMIT 10 } } }對(duì)應(yīng)的響應(yīng){ jsonrpc: 2.0, id: 1, result: { content: [ { type: text, text: id | name | email\n1 | Alice | aliceexample.com\n... } ] } }這里有幾個(gè)細(xì)節(jié)值得注意。id字段必須是唯一的同一個(gè)連接里不能重復(fù)否則響應(yīng)回來的時(shí)候分不清是哪個(gè)請(qǐng)求的結(jié)果。method字段用的是斜杠分隔的命名空間風(fēng)格比如tools/list、tools/call、resources/read這種命名方式讓方法名自帶層級(jí)信息一眼就能看出屬于哪個(gè)能力域。錯(cuò)誤處理也遵循 JSON-RPC 規(guī)范。如果調(diào)用出錯(cuò)響應(yīng)里會(huì)包含error字段{ jsonrpc: 2.0, id: 1, error: { code: -32602, message: Invalid params, data: Missing required field: sql } }錯(cuò)誤碼用的是 JSON-RPC 標(biāo)準(zhǔn)錯(cuò)誤碼比如-32700是解析錯(cuò)誤-32600是無效請(qǐng)求-32601是方法不存在-32602是參數(shù)無效。自定義錯(cuò)誤碼從-32000開始避免和標(biāo)準(zhǔn)碼沖突。3.2 STDIO 傳輸模式本地集成的首選方案STDIO 是 MCP 最常用的傳輸模式特別適合本地工具集成。工作原理很簡單Client 啟動(dòng) Server 進(jìn)程通過子進(jìn)程的標(biāo)準(zhǔn)輸入寫入請(qǐng)求通過標(biāo)準(zhǔn)輸出讀取響應(yīng)。每條消息以換行符分隔消息體是 JSON 格式。這種模式的優(yōu)勢在于零網(wǎng)絡(luò)開銷、零配置。你不需要開端口、不需要配防火墻、不需要處理跨域問題。Server 就是一個(gè)普通的命令行程序Client 啟動(dòng)它、跟它對(duì)話、用完關(guān)掉。對(duì)于本地開發(fā)工具、IDE 插件、桌面應(yīng)用來說這是最自然的集成方式。但 STDIO 也有它的限制。首先它只能在同一臺(tái)機(jī)器上運(yùn)行沒法跨網(wǎng)絡(luò)調(diào)用。其次Server 進(jìn)程的生命周期由 Client 管理Client 掛了 Server 也得跟著掛。第三標(biāo)準(zhǔn)輸出被協(xié)議占用Server 自己的日志只能寫到標(biāo)準(zhǔn)錯(cuò)誤或者文件里否則會(huì)污染協(xié)議消息。實(shí)操心得寫 MCP Server 的時(shí)候一定要把日志輸出到 stderr不要用 stdout。我見過好幾個(gè)項(xiàng)目因?yàn)榘颜{(diào)試信息打到 stdout 導(dǎo)致協(xié)議解析失敗排查了半天才發(fā)現(xiàn)是日志的問題。3.3 HTTP 傳輸模式遠(yuǎn)程服務(wù)的接入方式HTTP 模式適合 Server 部署在遠(yuǎn)程的場景。Client 通過 HTTP POST 請(qǐng)求發(fā)送 JSON-RPC 消息Server 返回 JSON 格式的響應(yīng)。和 STDIO 相比HTTP 模式多了網(wǎng)絡(luò)層的復(fù)雜性但也帶來了更好的可擴(kuò)展性。HTTP 模式下Server 可以獨(dú)立部署、獨(dú)立擴(kuò)縮容多個(gè) Client 可以同時(shí)連接同一個(gè) Server。這對(duì)于團(tuán)隊(duì)協(xié)作場景很有價(jià)值比如一個(gè)團(tuán)隊(duì)維護(hù)一個(gè)公共的 MCP Server所有人都通過 HTTP 接入不用每個(gè)人本地跑一份。不過 HTTP 模式也引入了新的問題。首先是認(rèn)證授權(quán)STDIO 模式下進(jìn)程隔離本身就是一種安全邊界HTTP 模式下需要額外的認(rèn)證機(jī)制。其次是連接管理HTTP 是無狀態(tài)協(xié)議但 MCP 的握手過程是有狀態(tài)的需要額外的機(jī)制來維護(hù)會(huì)話。第三是錯(cuò)誤處理網(wǎng)絡(luò)超時(shí)、連接斷開這些情況在 STDIO 模式下基本不會(huì)遇到但在 HTTP 模式下必須考慮。3.4 兩種傳輸模式的選型對(duì)比對(duì)比維度STDIO 模式HTTP 模式部署位置本地同機(jī)本地或遠(yuǎn)程網(wǎng)絡(luò)依賴無需要網(wǎng)絡(luò)并發(fā)支持單 Client多 Client認(rèn)證機(jī)制進(jìn)程隔離需要額外實(shí)現(xiàn)日志處理必須走 stderr無特殊限制適用場景IDE 插件、本地工具云端服務(wù)、團(tuán)隊(duì)共享實(shí)現(xiàn)復(fù)雜度低中高選型建議很直接本地工具用 STDIO遠(yuǎn)程服務(wù)用 HTTP。如果你的場景是給 IDE 寫插件、給桌面應(yīng)用加 AI 能力STDIO 是首選如果你要做一個(gè)團(tuán)隊(duì)共用的工具平臺(tái)HTTP 更合適。兩者不是互斥的同一個(gè) Server 可以同時(shí)支持兩種傳輸模式根據(jù)部署環(huán)境切換。4. SDK 選型與開發(fā)實(shí)操指南4.1 官方 SDK 與社區(qū) SDK 的取舍MCP 官方提供了 TypeScript 和 Python 兩個(gè) SDK社區(qū)也有 Go、Java、Rust 等語言的實(shí)現(xiàn)。選 SDK 的時(shí)候要考慮幾個(gè)因素語言生態(tài)匹配度、維護(hù)活躍度、文檔完善程度。TypeScript SDK 是目前最成熟的官方維護(hù)更新及時(shí)文檔也最全。如果你做的是 Node.js 應(yīng)用或者前端工具直接用官方 TS SDK 就行。Python SDK 同樣官方維護(hù)適合做數(shù)據(jù)類工具或者和 AI 框架集成。社區(qū) SDK 里 Go 和 Rust 的完成度比較高Java 的還在完善中。注意選社區(qū) SDK 之前一定要看最近的 commit 時(shí)間和 issue 響應(yīng)速度。MCP 協(xié)議本身還在演進(jìn)SDK 跟不上協(xié)議更新的話會(huì)很痛苦。我踩過一次坑用了一個(gè)半年沒更新的社區(qū) SDK結(jié)果協(xié)議升級(jí)后完全不兼容只能推倒重來。4.2 用 TypeScript SDK 搭建第一個(gè) MCP Server先裝依賴npm install modelcontextprotocol/sdk然后寫一個(gè)最簡單的 Server提供一個(gè)查詢當(dāng)前時(shí)間的工具import { Server } from modelcontextprotocol/sdk/server/index.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { CallToolRequestSchema, ListToolsRequestSchema, } from modelcontextprotocol/sdk/types.js; const server new Server( { name: time-server, version: 1.0.0 }, { capabilities: { tools: {} } } ); server.setRequestHandler(ListToolsRequestSchema, async () ({ tools: [ { name: get_current_time, description: 獲取當(dāng)前系統(tǒng)時(shí)間, inputSchema: { type: object, properties: { timezone: { type: string, description: 時(shí)區(qū)如 Asia/Shanghai, }, }, }, }, ], })); server.setRequestHandler(CallToolRequestSchema, async (request) { if (request.params.name get_current_time) { const tz request.params.arguments?.timezone || Asia/Shanghai; const now new Date().toLocaleString(zh-CN, { timeZone: tz }); return { content: [{ type: text, text: 當(dāng)前時(shí)間${now} }], }; } throw new Error(Unknown tool: ${request.params.name}); }); const transport new StdioServerTransport(); await server.connect(transport);這段代碼做了三件事創(chuàng)建 Server 實(shí)例并聲明tools能力注冊(cè)兩個(gè)請(qǐng)求處理器一個(gè)處理工具列表查詢一個(gè)處理工具調(diào)用用 STDIO 傳輸連接 Server。ListToolsRequestSchema對(duì)應(yīng)的處理器返回工具列表每個(gè)工具包含名稱、描述和輸入?yún)?shù)的 JSON Schema。CallToolRequestSchema對(duì)應(yīng)的處理器根據(jù)工具名執(zhí)行具體邏輯返回結(jié)果內(nèi)容。4.3 工具定義的關(guān)鍵細(xì)節(jié)inputSchema 怎么寫才規(guī)范inputSchema用的是 JSON Schema 規(guī)范寫得好不好直接影響模型對(duì)工具的理解準(zhǔn)確率。幾個(gè)實(shí)操要點(diǎn)第一description字段要寫清楚工具的用途和適用場景不要只寫“查詢數(shù)據(jù)”這種模糊描述要寫“根據(jù) SQL 語句查詢 PostgreSQL 數(shù)據(jù)庫返回查詢結(jié)果”。模型靠這個(gè)描述來判斷什么時(shí)候該調(diào)用這個(gè)工具。第二參數(shù)描述要具體。比如timezone參數(shù)寫“時(shí)區(qū)”不如寫“IANA 時(shí)區(qū)標(biāo)識(shí)符如 Asia/Shanghai、America/New_York”。模型看到具體示例后生成參數(shù)值的準(zhǔn)確率會(huì)明顯提高。第三必填參數(shù)用required數(shù)組聲明可選參數(shù)給默認(rèn)值。不要讓模型去猜哪些參數(shù)必須傳協(xié)議層面能約束的就不要留給模型判斷。第四參數(shù)類型盡量用基礎(chǔ)類型。字符串、數(shù)字、布爾值這些模型理解得最好復(fù)雜的嵌套對(duì)象容易出錯(cuò)。如果確實(shí)需要復(fù)雜結(jié)構(gòu)考慮拆成多個(gè)簡單工具。4.4 資源與提示模板的實(shí)現(xiàn)方式除了工具M(jìn)CP 還支持資源和提示模板兩種能力。資源用來暴露可讀取的數(shù)據(jù)比如文件內(nèi)容、數(shù)據(jù)庫記錄、API 返回結(jié)果。提示模板用來提供預(yù)定義的提示詞模板方便 Client 直接調(diào)用。資源的實(shí)現(xiàn)和工具類似注冊(cè)resources/list和resources/read兩個(gè)處理器。resources/list返回資源列表每個(gè)資源有 URI 和描述resources/read根據(jù) URI 返回具體內(nèi)容。提示模板注冊(cè)prompts/list和prompts/get兩個(gè)處理器。prompts/list返回模板列表prompts/get根據(jù)模板名和參數(shù)返回填充好的提示詞。這三種能力的組合使用可以覆蓋大部分場景。工具負(fù)責(zé)執(zhí)行操作資源負(fù)責(zé)讀取數(shù)據(jù)提示模板負(fù)責(zé)提供預(yù)定義的交互模式。實(shí)際項(xiàng)目中不用全部實(shí)現(xiàn)按需選擇即可。5. 常見問題與排查技巧實(shí)錄5.1 連接建立失敗握手階段的典型問題握手失敗是最常見的問題表現(xiàn)是 Client 啟動(dòng)后一直卡在初始化階段或者直接報(bào)連接錯(cuò)誤。排查思路按順序來先看協(xié)議版本是否匹配。Client 和 Server 的協(xié)議版本不一致時(shí)握手會(huì)失敗。檢查雙方聲明的protocolVersion字段確保在同一個(gè)大版本內(nèi)。再看能力聲明是否合法。Server 聲明的能力必須是協(xié)議支持的拼寫錯(cuò)誤或者用了未定義的能力名都會(huì)導(dǎo)致握手失敗。比如把tools寫成toolClient 解析不了就直接斷開。最后看傳輸層是否正常。STDIO 模式下檢查 Server 進(jìn)程是否成功啟動(dòng)、是否有權(quán)限問題、stdout 是否被其他輸出污染。HTTP 模式下檢查網(wǎng)絡(luò)連通性、端口是否被占用、是否有代理攔截。5.2 工具調(diào)用無響應(yīng)消息路由的排查方法工具調(diào)用發(fā)出去了但收不到響應(yīng)可能的原因有幾個(gè)。最常見的是id字段重復(fù)同一個(gè)連接里兩個(gè)請(qǐng)求用了相同的id響應(yīng)回來的時(shí)候匹配錯(cuò)了。解決辦法是維護(hù)一個(gè)自增計(jì)數(shù)器每個(gè)請(qǐng)求分配唯一id。另一個(gè)原因是 Server 端的處理器拋了異常但沒有正確返回錯(cuò)誤響應(yīng)。JSON-RPC 規(guī)范要求即使出錯(cuò)也要返回帶error字段的響應(yīng)如果 Server 直接崩潰或者靜默吞掉異常Client 就會(huì)一直等。寫 Server 的時(shí)候一定要用 try-catch 包住處理器邏輯確保任何情況下都有響應(yīng)返回。還有一種情況是消息體太大被截?cái)?。STDIO 模式下如果單條消息超過緩沖區(qū)大小可能會(huì)被截?cái)鄬?dǎo)致解析失敗。解決辦法是控制單次返回的數(shù)據(jù)量大結(jié)果集分頁返回。5.3 常見問題速查表問題現(xiàn)象可能原因排查方法解決方案握手超時(shí)協(xié)議版本不匹配檢查雙方 protocolVersion統(tǒng)一協(xié)議版本連接斷開stdout 被日志污染檢查 Server 輸出日志改到 stderr調(diào)用無響應(yīng)id 重復(fù)或異常未捕獲檢查 id 生成邏輯和 try-catch唯一 id 異常兜底參數(shù)解析失敗inputSchema 定義有誤校驗(yàn) JSON Schema 合法性修正 schema 定義結(jié)果截?cái)嘞Ⅲw過大檢查緩沖區(qū)大小分頁返回或增大緩沖區(qū)并發(fā)沖突多請(qǐng)求共享狀態(tài)檢查全局變量使用加鎖或改為無狀態(tài)5.4 性能優(yōu)化的幾個(gè)實(shí)操技巧STDIO 模式下每次工具調(diào)用都是一次進(jìn)程間通信雖然比網(wǎng)絡(luò)調(diào)用快但頻繁調(diào)用時(shí)累積延遲也不可忽視。優(yōu)化思路是批量處理把多個(gè)小請(qǐng)求合并成一個(gè)批量請(qǐng)求減少通信次數(shù)。Server 端的工具實(shí)現(xiàn)要注意避免阻塞。如果某個(gè)工具執(zhí)行時(shí)間較長考慮改成異步執(zhí)行加輪詢結(jié)果的方式不要讓整個(gè)連接卡住。JSON-RPC 本身支持異步響應(yīng)可以先返回一個(gè)“任務(wù)已接受”的響應(yīng)后續(xù)通過通知機(jī)制推送結(jié)果。資源讀取要加緩存。如果某個(gè)資源的內(nèi)容不經(jīng)常變化在 Server 端做一層緩存避免每次都重新讀取。緩存失效策略可以根據(jù)資源類型來定文件類資源用 mtime 判斷數(shù)據(jù)庫類資源用版本號(hào)或者時(shí)間戳判斷。實(shí)操心得調(diào)試 MCP 的時(shí)候在 Client 和 Server 之間加一個(gè)日志中間層把雙向消息都記錄下來。排查問題時(shí)直接看日志比在代碼里打斷點(diǎn)效率高得多。我一般用一個(gè)小腳本包裝 STDIO 傳輸把每條消息同時(shí)寫到文件里事后分析非常方便。6. 從架構(gòu)視角看 MCP 的擴(kuò)展性與邊界6.1 多 Server 編排一個(gè) Client 連接多個(gè)工具源實(shí)際項(xiàng)目中一個(gè) Client 往往需要連接多個(gè) MCP Server。比如一個(gè) IDE 插件可能同時(shí)需要代碼分析 Server、文檔查詢 Server、數(shù)據(jù)庫操作 Server。MCP 協(xié)議本身沒有限制 Client 只能連一個(gè) Server你可以維護(hù)多個(gè)連接根據(jù)工具名路由到對(duì)應(yīng)的 Server。路由策略有兩種一種是按命名空間前綴區(qū)分比如db.query路由到數(shù)據(jù)庫 Serverdoc.search路由到文檔 Server另一種是維護(hù)一個(gè)工具到 Server 的映射表Client 啟動(dòng)時(shí)從各個(gè) Server 拉取工具列表合并后建立索引。多 Server 場景下要注意工具名沖突。兩個(gè) Server 都提供了叫search的工具Client 需要做重命名或者加前綴。建議在 Server 命名時(shí)就加上領(lǐng)域前綴比如db_search、doc_search從源頭避免沖突。6.2 安全邊界STDIO 與 HTTP 的權(quán)限模型差異STDIO 模式的安全模型基于進(jìn)程隔離。Server 進(jìn)程以當(dāng)前用戶權(quán)限運(yùn)行能訪問的資源就是當(dāng)前用戶能訪問的資源。Client 啟動(dòng) Server 時(shí)可以通過環(huán)境變量傳遞必要的憑證Server 本身不需要額外的認(rèn)證邏輯。HTTP 模式的安全模型需要顯式設(shè)計(jì)。Server 暴露在網(wǎng)絡(luò)上任何人都可能發(fā)起請(qǐng)求必須有認(rèn)證機(jī)制。常見的做法是用 API Key 或者 OAuth TokenClient 在請(qǐng)求頭里帶上憑證Server 驗(yàn)證后放行。授權(quán)粒度可以做到工具級(jí)別不同 Client 可以訪問不同的工具集。注意HTTP 模式下千萬不要把 Server 直接暴露在公網(wǎng)而不加認(rèn)證。MCP Server 能執(zhí)行的操作可能包括文件讀寫、數(shù)據(jù)庫查詢、命令執(zhí)行未授權(quán)訪問的后果很嚴(yán)重。至少加一層 API Key 驗(yàn)證有條件的話上完整的 OAuth 流程。6.3 協(xié)議演進(jìn)MCP 后續(xù)可能的發(fā)展方向MCP 協(xié)議目前還在快速演進(jìn)中。從社區(qū)討論和官方路線圖來看幾個(gè)方向比較明確一是增加更多的傳輸模式支持比如 WebSocket以適應(yīng)實(shí)時(shí)性要求更高的場景二是完善流式響應(yīng)機(jī)制讓大結(jié)果集可以分塊返回三是增強(qiáng)能力協(xié)商的粒度支持更細(xì)粒度的權(quán)限控制。對(duì)于開發(fā)者來說保持關(guān)注官方 SDK 的更新及時(shí)跟進(jìn)協(xié)議變化就行。自己實(shí)現(xiàn) Server 的時(shí)候盡量把協(xié)議層和業(yè)務(wù)邏輯分開協(xié)議升級(jí)時(shí)只需要改協(xié)議適配層業(yè)務(wù)代碼不用動(dòng)。這是我在多個(gè)項(xiàng)目里驗(yàn)證過的做法能顯著降低升級(jí)成本。6.4 實(shí)際項(xiàng)目中的架構(gòu)決策記錄最后分享一個(gè)真實(shí)項(xiàng)目的架構(gòu)決策過程。當(dāng)時(shí)我們要給一個(gè)內(nèi)部數(shù)據(jù)分析平臺(tái)加 AI 助手功能需要接入數(shù)據(jù)庫查詢、報(bào)表生成、文件導(dǎo)出三個(gè)能力。評(píng)估了三種方案直接 Function Calling、自研插件系統(tǒng)、MCP。Function Calling 的問題是工具描述太長三個(gè)能力的描述加起來快兩千 token每次對(duì)話都要帶上成本太高。自研插件系統(tǒng)的問題是后續(xù)擴(kuò)展麻煩每加一個(gè)能力就要改框架代碼。MCP 的方案是把三個(gè)能力分別做成三個(gè) ServerClient 按需連接工具描述只在握手時(shí)拉取一次后續(xù)調(diào)用不占上下文。最終選了 MCP實(shí)際落地下來效果符合預(yù)期。三個(gè) Server 獨(dú)立開發(fā)、獨(dú)立部署互不影響。Client 端的代碼量比預(yù)想的少因?yàn)閰f(xié)議層的事情 SDK 都處理了。唯一花時(shí)間的是調(diào)試握手階段的問題主要是協(xié)議版本和能力聲明的細(xì)節(jié)踩了幾個(gè)坑之后就跑通了。這個(gè)項(xiàng)目讓我對(duì) MCP 的定位有了更清晰的認(rèn)識(shí)它不是銀彈不能解決所有工具集成問題但在“多工具、多團(tuán)隊(duì)、需要標(biāo)準(zhǔn)化”的場景下它確實(shí)能顯著降低集成成本。如果你的場景是單一工具、單一團(tuán)隊(duì)用不用 MCP 差別不大但如果是多個(gè)工具需要統(tǒng)一接入、多個(gè)團(tuán)隊(duì)需要協(xié)作開發(fā)MCP 的價(jià)值就體現(xiàn)出來了。