MCP協(xié)議:AI連接世界的標(biāo)準(zhǔn)
MCP(Model Context Protocol,模型上下文協(xié)議)是Anthropic在2024年底發(fā)布的開放協(xié)議,旨在為AI模型與外部工具、數(shù)據(jù)源建立標(biāo)準(zhǔn)化的通信方式。本文深入解析MCP的設(shè)計(jì)原理、協(xié)議架構(gòu)、以及在AI工程實(shí)踐中的應(yīng)用。
一、為什么需要MCP
1.1 AI應(yīng)用的核心挑戰(zhàn)
當(dāng)前AI應(yīng)用面臨一個(gè)根本性問題:AI模型是孤立的——它只能看到訓(xùn)練時(shí)的知識(shí),無法直接與外部世界交互。RAG系統(tǒng)解決了知識(shí)獲取問題,但工具調(diào)用、數(shù)據(jù)寫入、多系統(tǒng)協(xié)同仍然缺乏統(tǒng)一標(biāo)準(zhǔn)。
典型場(chǎng)景:
AI需要從數(shù)據(jù)庫讀取實(shí)時(shí)數(shù)據(jù)
AI需要調(diào)用外部API完成特定操作
AI需要向多個(gè)外部系統(tǒng)寫入數(shù)據(jù)
AI需要訂閱實(shí)時(shí)事件流
每個(gè)AI應(yīng)用都在重復(fù)造輪子:自定義的工具調(diào)用格式、自定義的API適配層、自定義的錯(cuò)誤處理。
1.2 MCP的核心價(jià)值
MCP的定位是成為"AI世界的USB接口"——提供一個(gè)標(biāo)準(zhǔn)化的方式讓AI模型與任何外部系統(tǒng)交互。
USB接口解決的問題: - 不需要為每個(gè)設(shè)備設(shè)計(jì)專門的接口 - 設(shè)備插上就能用 - 標(biāo)準(zhǔn)化意味著生態(tài)化 MCP解決的問題: - 不需要為每個(gè)外部系統(tǒng)設(shè)計(jì)專門的適配 - 工具接入一次,任何AI模型都能調(diào)用 - 標(biāo)準(zhǔn)化促進(jìn)生態(tài)繁榮
二、MCP協(xié)議架構(gòu)
2.1 核心組件
┌─────────────────────────────────────────────────────────────┐
│ AI Application │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MCP Client │ │
│ │ - 維護(hù)與Server的連接 │ │
│ │ - 序列化/反序列化消息 │ │
│ │ - 處理協(xié)議握手 │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
│ stdio / HTTP + SSE
┌──────────────────────────▼──────────────────────────────────┐
│ MCP Server (進(jìn)程) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Protocol Engine │ │
│ │ - 消息路由 │ │
│ │ - 能力協(xié)商 │ │
│ │ - 錯(cuò)誤處理 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Tool Handler │ │
│ │ - 暴露工具清單 │ │
│ │ - 執(zhí)行工具調(diào)用 │ │
│ │ - 返回結(jié)果格式化 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Resource Handler │ │
│ │ - 管理可讀取的資源 │ │
│ │ - 處理資源訂閱 │ │
│ │ - 內(nèi)容緩存 │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ External Systems │
│ - REST APIs - Databases - File Systems - etc. │
└─────────────────────────────────────────────────────────────┘
2.2 通信協(xié)議
MCP支持兩種傳輸方式:
stdio模式(適合本地/CLI工具):
AI App → MCP Client → stdin → MCP Server → External System
↑ ↓
└────── stdout ←───────┘
HTTP + SSE模式(適合遠(yuǎn)程服務(wù)):
AI App → MCP Client ──── HTTP POST /message ──→ MCP Server
↑ ↓
└──────── SSE (Server-Sent Events) ←──────────┘
2.3 消息類型
MCP定義了四種核心消息類型:
// 1. Initialize - 握手協(xié)商 {"jsonrpc":"2.0","id":1,"method":"initialize", "params": { "protocolVersion":"2024-11-05", "capabilities": {"roots": {},"tools": {}}, "clientInfo": {"name":"claude-desktop","version":"1.0"} }} {"jsonrpc":"2.0","id":1,"result": { "protocolVersion":"2024-11-05", "capabilities": {"tools": {},"resources": {}}, "serverInfo": {"name":"filesystem-server","version":"1.0"} }} // 2. Tools/List - 列出可用工具 {"jsonrpc":"2.0","id":2,"method":"tools/list"} {"jsonrpc":"2.0","id":2,"result": { "tools": [ {"name":"read_file","description":"讀取文件內(nèi)容", "inputSchema": {"type":"object","properties": { "path": {"type":"string"} }}}, {"name":"write_file","description":"寫入文件內(nèi)容", "inputSchema": {"type":"object","properties": { "path": {"type":"string"}, "content": {"type":"string"} }}} ] }} // 3. Tools/Call - 調(diào)用工具 {"jsonrpc":"2.0","id":3,"method":"tools/call", "params": { "name":"read_file", "arguments": {"path":"/etc/passwd"} }} {"jsonrpc":"2.0","id":3,"result": { "content": [{"type":"text","text":"root0root:/root:/bin/bash ..."}] }} // 4. Resources - 資源訪問 {"jsonrpc":"2.0","id":4,"method":"resources/list"} {"jsonrpc":"2.0","id":4,"result": { "resources": [ {"uri":"file:///project/config.yaml","name":"Config","mimeType":"application/yaml"} ] }}
三、MCP Server開發(fā)
frommcp.server.fastmcpimportFastMCP
# 初始化MCP Server
mcp = FastMCP("filesystem-server")
@mcp.tool()
defread_file(path: str, encoding: str ="utf-8")-> str:
"""讀取文件內(nèi)容"""
withopen(path,'r', encoding=encoding)asf:
returnf.read()
@mcp.tool()
defwrite_file(path: str, content: str)-> dict:
"""寫入文件內(nèi)容"""
withopen(path,'w', encoding='utf-8')asf:
f.write(content)
return{"success":True,"path": path,"bytes": len(content)}
@mcp.tool()
deflist_directory(path: str)-> list[dict]:
"""列出目錄內(nèi)容"""
importos
items = []
foriteminos.listdir(path):
full_path = os.path.join(path, item)
items.append({
"name": item,
"type":"dir"ifos.path.isdir(full_path)else"file",
"size": os.path.getsize(full_path)ifos.path.isfile(full_path)elseNone
})
returnitems
@mcp.resource("file://{path}")
deffile_resource(path: str)-> str:
"""動(dòng)態(tài)資源訪問"""
withopen(path,'r')asf:
returnf.read()
# 啟動(dòng)服務(wù)器
if__name__ =="__main__":
mcp.run()
3.2 帶復(fù)雜參數(shù)的工具
@mcp.tool()
defsearch_codebase(
query: str,
file_pattern: str ="*.py",
case_sensitive: bool = False,
max_results: int =50
)-> list[dict]:
"""
在代碼庫中搜索代碼
Args:
query: 搜索關(guān)鍵詞
file_pattern: 文件名模式 (glob格式)
case_sensitive: 是否區(qū)分大小寫
max_results: 最大返回結(jié)果數(shù)
"""
importglob
importos
results = []
forfile_pathinglob.glob(file_pattern, recursive=True):
ifnotos.path.isfile(file_path):
continue
try:
withopen(file_path,'r', encoding='utf-8', errors='ignore')asf:
lines = f.readlines()
fori, lineinenumerate(lines):
ifcase_sensitive:
match = queryinline
else:
match = query.lower()inline.lower()
ifmatch:
results.append({
"file": file_path,
"line": i +1,
"content": line.strip(),
"context": lines[max(0, i-2):i] + lines[i+1:min(len(lines), i+3)]
})
iflen(results) >= max_results:
returnresults
exceptException:
continue
returnresults
3.3 流式響應(yīng)工具
fromtypingimportAsyncIterator
@mcp.tool()
asyncdefstream_log_tail(
path: str,
lines: int =100
)-> AsyncIterator[dict]:
"""流式讀取日志文件最后N行"""
importasyncio
withopen(path,'r')asf:
all_lines = f.readlines()
last_lines = all_lines[-lines:]
forlineinlast_lines:
yield{"content": line.strip()}
awaitasyncio.sleep(0.1) # 模擬實(shí)時(shí)推送
四、MCP Client集成
4.1 Python Client實(shí)現(xiàn)
frommcpimportClientSession, StdioServerParameters
frommcp.client.stdioimportstdio_client
importasyncio
classMCPClient:
def__init__(self, server_command: list[str]):
self.server_command = server_command
asyncdefinitialize(self):
server_params = StdioServerParameters(
command=self.server_command[0],
args=self.server_command[1:]
)
asyncwithstdio_client(server_params)as(read, write):
self.session = ClientSession(read, write)
awaitself.session.initialize()
# 獲取服務(wù)器能力
response =awaitself.session.get_server_capabilities()
print(f"Server capabilities:{response.capabilities}")
asyncdeflist_tools(self)-> list[dict]:
response =awaitself.session.list_tools()
return[tool.model_dump()fortoolinresponse.tools]
asyncdefcall_tool(
self,
tool_name: str,
arguments: dict
)-> dict:
result =awaitself.session.call_tool(tool_name, arguments)
returnresult.content[0].model_dump()
# 使用示例
asyncdefmain():
client = MCPClient(["python","filesystem_server.py"])
awaitclient.initialize()
# 列出可用工具
tools =awaitclient.list_tools()
print("Available tools:", [t["name"]fortintools])
# 調(diào)用工具
result =awaitclient.call_tool("read_file", {"path":"/tmp/test.txt"})
print("File content:", result["text"])
asyncio.run(main())
4.2 與LangChain集成
fromlangchain_mcp_adapters.clientimportMultiServerMCPClient fromlangchain_openaiimportChatOpenAI fromlanggraph.prebuiltimportcreate_react_agent # 初始化MCP客戶端,連接多個(gè)服務(wù)器 client = MultiServerMCPClient({ "filesystem": { "command":"python", "args": ["/path/to/filesystem_server.py"] }, "database": { "command":"python", "args": ["/path/to/database_server.py"] } }) # 獲取所有工具 tools = client.get_tools() # 創(chuàng)建Agent llm = ChatOpenAI(model="gpt-4o") agent = create_react_agent(llm, tools) # 運(yùn)行Agent result = agent.invoke({ "messages": [{"role":"user","content":"讀取/tmp/config.yaml文件并總結(jié)關(guān)鍵配置"}] })
五、生產(chǎn)環(huán)境最佳實(shí)踐
5.1 Server健康檢查
importasyncio
frommcpimportClientSession
frommcp.client.stdioimportstdio_client
classMCPClientWithHealthCheck:
def__init__(self, server_params, health_check_timeout: float =5.0):
self.server_params = server_params
self.health_check_timeout = health_check_timeout
self._session =None
asyncdefhealth_check(self)-> bool:
"""檢查MCP Server是否可用"""
try:
asyncwithstdio_client(self.server_params)as(read, write):
session = ClientSession(read, write)
awaitasyncio.wait_for(
session.initialize(),
timeout=self.health_check_timeout
)
# 嘗試列出工具
awaitsession.list_tools()
returnTrue
exceptasyncio.TimeoutError:
returnFalse
exceptExceptionase:
print(f"Health check failed:{e}")
returnFalse
asyncdefget_session(self)-> ClientSession:
ifself._sessionisNone:
asyncwithstdio_client(self.server_params)as(read, write):
self._session = ClientSession(read, write)
awaitself._session.initialize()
returnself._session
5.2 錯(cuò)誤處理與重試
importasyncio
frommcp.errorimportMCPError
classResilientMCPClient:
def__init__(self, server_params, max_retries: int =3):
self.server_params = server_params
self.max_retries = max_retries
asyncdefcall_with_retry(
self,
tool_name: str,
arguments: dict
)-> dict:
last_error =None
forattemptinrange(self.max_retries):
try:
asyncwithstdio_client(self.server_params)as(read, write):
session = ClientSession(read, write)
awaitsession.initialize()
result =awaitsession.call_tool(tool_name, arguments)
returnresult.content[0].model_dump()
exceptMCPErrorase:
# 協(xié)議級(jí)錯(cuò)誤,不重試
raise(f"MCP protocol error:{e}")
exceptExceptionase:
last_error = e
ifattempt < self.max_retries -?1:
? ? ? ? ? ? ? ? ? ??await?asyncio.sleep(2?** attempt) ?# 指數(shù)退避
? ? ? ? ? ? ? ??continue
? ? ? ??raise?RuntimeError(f"Failed after?{self.max_retries}?attempts:?{last_error}")
5.3 安全考慮
MCP的工具調(diào)用執(zhí)行在Server進(jìn)程中,需要注意:
# Server端:輸入驗(yàn)證
@mcp.tool()
defdelete_file(path: str)-> dict:
"""刪除文件(需要嚴(yán)格的安全檢查)"""
importos
# 禁止刪除系統(tǒng)關(guān)鍵路徑
forbidden_paths = ["/","/etc","/usr","/bin","/sbin","/var"]
abs_path = os.path.abspath(path)
forforbiddeninforbidden_paths:
ifabs_path.startswith(forbidden):
raiseValueError(f"Cannot delete files in{forbidden}")
# 禁止跨目錄刪除
if".."inpath:
raiseValueError("Path traversal not allowed")
# 檢查文件是否存在
ifnotos.path.exists(abs_path):
return{"success":False,"error":"File not found"}
os.remove(abs_path)
return{"success":True,"path": path}
六、主流MCP Server生態(tài)
6.1 官方及社區(qū)Server
| Server | 功能 | 維護(hù)方 |
|---|---|---|
| filesystem | 本地文件系統(tǒng)訪問 | Anthropic官方 |
| slack | Slack消息讀寫 | Anthropic官方 |
| github | GitHub API操作 | Anthropic官方 |
| puppeteer | 瀏覽器自動(dòng)化 | 社區(qū) |
| postgresql | PostgreSQL查詢 | 社區(qū) |
| Brave Search | 網(wǎng)頁搜索 | 社區(qū) |
6.2 Server發(fā)現(xiàn)與配置
// claude_desktop_config.json
{
"mcpServers": {
"filesystem": {
"command":"npx",
"args": ["-y","@anthropic/mcp-server-filesystem"],
"config": {
"allowedDirectories": ["/Users/me/projects","/tmp"]
}
},
"github": {
"command":"npx",
"args": ["-y","@anthropic/mcp-server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN":"ghp_xxxx"
}
},
"postgresql": {
"command":"uvx",
"args": ["mcp-server-postgres","--host","localhost","--port","5432"],
"env": {
"DATABASE_URL":"postgresql://user:pass@localhost/mydb"
}
}
}
}
七、協(xié)議演進(jìn)與未來
MCP協(xié)議仍處于活躍開發(fā)中,以下是值得關(guān)注的方向:
7.1 采樣能力(Prompt Caching的未來)
當(dāng)前協(xié)議支持Server向Client"推送"數(shù)據(jù)的能力有限。未來版本可能會(huì)增強(qiáng)雙向通信能力。
7.2 多Agent協(xié)作
MCP的設(shè)計(jì)天然支持多Agent場(chǎng)景:
多個(gè)AI Agent通過各自的MCP Client連接同一Server
Server作為協(xié)調(diào)者管理資源訪問沖突
支持Agent間的消息傳遞
# 多Agent共享MCP Server
classSharedMCPBridge:
def__init__(self, server):
self.server = server
self.agents = {}
defregister_agent(self, agent_id: str, client_session):
self.agents[agent_id] = client_session
asyncdefbroadcast(self, message: dict, from_agent: str):
"""向所有Agent廣播消息"""
foragent_id, sessioninself.agents.items():
ifagent_id != from_agent:
awaitsession.send_notification("agent/message", message)
總結(jié)
MCP協(xié)議代表了AI應(yīng)用架構(gòu)的一個(gè)重要演進(jìn)方向:
核心價(jià)值:
標(biāo)準(zhǔn)化:統(tǒng)一的工具調(diào)用協(xié)議
生態(tài)化:一次實(shí)現(xiàn),到處可用
安全性:清晰的權(quán)限邊界
工程實(shí)踐要點(diǎn):
Server端做好輸入驗(yàn)證和權(quán)限控制
Client端實(shí)現(xiàn)健康檢查和重試機(jī)制
生產(chǎn)環(huán)境注意監(jiān)控工具調(diào)用延遲和錯(cuò)誤率
合理設(shè)計(jì)工具粒度,避免過度抽象
隨著MCP生態(tài)的成熟,我們可以期待看到更多標(biāo)準(zhǔn)化的工具Server出現(xiàn),AI應(yīng)用的開發(fā)效率將顯著提升。
-
AI
+關(guān)注
關(guān)注
91文章
41026瀏覽量
302545 -
模型
+關(guān)注
關(guān)注
1文章
3813瀏覽量
52257 -
MCP
+關(guān)注
關(guān)注
0文章
294瀏覽量
15079
原文標(biāo)題:MCP 協(xié)議:賦能 AI 連接世界的核心通用標(biāo)準(zhǔn)
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
物聯(lián)網(wǎng)的內(nèi)部核心架構(gòu)介紹
如何使用MCP2515和TJA1050構(gòu)成CAN節(jié)點(diǎn)通信
MCP2515協(xié)議控制器與MCU的連接是如何實(shí)現(xiàn)的
MCP6541/MCP6542/MCP6543/MCP654
IrDA標(biāo)準(zhǔn)協(xié)議??刂破髦?b class='flag-5'>MCP2140數(shù)據(jù)手冊(cè)
探究USB協(xié)議架構(gòu)及驅(qū)動(dòng)架構(gòu)
羅格科技全線產(chǎn)品支持MCP協(xié)議,構(gòu)建智慧稅務(wù)新生態(tài)
技術(shù)解讀:MCP協(xié)議以及SmartBear API Hub在MCP開發(fā)中的關(guān)鍵作用
【MCP】同時(shí)支持stdio,streamableHttpless和sse三種協(xié)議的MCP服務(wù)框架
MCP協(xié)議的設(shè)計(jì)原理和核心架構(gòu)
評(píng)論