這個的思路很簡單就不多介紹了,主要是function calling有什么問題?function calling最大的問題就在于它的工具量非常大,一個簡單的外部函數往往就要上百行的代碼,并且,為了讓大模型認識這些外部函數,還需要為每個外部函數編寫一個json schema格式的功能說明,此外還要精心設計一個提示詞模板才能提高function calling響應的準確率。

所以MCP的目標,就是為了簡化這一過程。先統一名稱。把大模型的運行環境成為MCP Clinet,也就是MCP客戶端,同時,把外部函數運行環境作為MCP Server,MCP服務端。

然后,統一客戶端和服務端的運行規范.并且要求MCP客戶端和服務端之間,也統一按照某個既定的提示詞模板進行通信.

這樣做目前最大的好處就在于MCP服務器的開發成為一個特定的模板,并且只要開發了一個MCP server之后,大家也就都能夠直接進行使用.比如查詢天氣,網頁爬取,查詢本地SQL等等通用需求.

于是github中的MCP成堆出現,大模型能夠使用的工具不斷增多,

關于agent的入門學習理論,主要包含的四個模塊及其作用方面.

環境構建

我看大模型使用的最多的環境是uv的虛擬環境,這里稍微講一下他們之間的關系.conda是一個跨語言的包和環境的管理工具(不止有python環境),uv則是一個超快的,主要用于python生態,和pip poetry是一類的

這里我們選擇uv來構建,也借著學習一下uv的安裝和命令,首先是通過pip來安裝uv,python的版本的話優先考慮py3.11的.

pip install uv

安裝依賴庫

uv pip install requests

# 與pip install 類似,但是更快

創建虛擬環境.到這里才是真正使用uv創建虛擬環境:

uv venv myenv

這里不像conda,可以指定自己的python版本,這里默認就是使用當前python版本進行虛擬的.類似于運行了:python -m venv myenv.
然后就可以激活環境:

source myenv/bin/activate

windows中則是:

myenvScriptsactivate

# Windows

然后在虛擬環境中都要通過uv開頭的命令來運行文件,這樣能夠更加高效.

上面主要是uv的一些基礎內容,接下來我們正式建立mcp client和mcp server
創建mcp客戶端:
我用的是自己在win上安裝的py3.8

uv init mcp-client
cd mcp-client

然后創建虛擬環境并進入:

uv venv
.venvScriptsactivate

接下來安裝一些依賴庫:

uv add mcp openai python-dotenv

報錯了:

因為mcp 包要求 Python 版本大于等于 3.10,這就導致依賴解析失敗。所以我們推薦的還是py3.11的版本.

那怎么通過uv創建不同的python環境呢?

uv沒有這樣的功能.所以說我們還是需要一個conda,創建一個py3.11的版本,然后重新直線上述過程.還挺無語的,但是要想要uv的快速原型功能也只好這樣了…

conda create -n mcp_server python=3.11
conda activate mcp_server

然后重新uv:

uv init mcp-client
cd mcp-client
uv venv
.venvScriptsactivate
uv add mcp openai python-dotenv

python雙重環境…
安裝完畢之后:

創建客戶端client.py,是調用大模型的核心部分:

if name == "main":
asyncio.run(main())

# 加載 .env 文件,確保 API Key 受到保護
load_dotenv()

class MCPClient:
def __init__(self):

"""初始化 MCP 客戶端"""
self.exit_stack = AsyncExitStack()
self.openai_api_key = os.getenv("OPENAI_API_KEY")

# 讀取 OpenAI API Key
self.base_url = os.getenv("BASE_URL")

# 讀取 BASE YRL
self.model = os.getenv("MODEL")

# 讀取 model

if not self.openai_api_key:
raise ValueError("? 未找到 [OpenAI](http://www.dlbhg.com/provider/uid202405280134182e2ed4) [API](http://www.dlbhg.com/wiki/api/) Key,請在 .env 文件中設置 OPENAI_API_KEY")

self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url)

async def process_query(self, query: str) -> str:
"""[調用 OpenAI API](http://www.dlbhg.com/blog/ua-using-pycharm-to-call-api-guide) 處理用戶查詢"""
messages = [{"role": "system", "content": "你是一個智能助手,幫助用戶回答問題。"},
{"role": "user", "content": query}]

try:

# 調用 OpenAI API
response = await asyncio.get_event_loop().run_in_executor(
None,
lambda: self.client.chat.completions.create(
model=self.model,
messages=messages,
stream=False
)
)
return response.choices[0].message.content
except Exception as e:
return f"?? 調用 OpenAI API 時出錯: {str(e)}"

async def chat_loop(self):
"""運行交互式聊天循環"""
print("n?? MCP 客戶端已啟動!輸入 'quit' 退出")

while True:
try:
query = input("n你: ").strip()
if query.lower() == 'quit':
break

response = await self.process_query(query)

# 發送用戶輸入到 OpenAI API
print(f"n?? OpenAI: {response}")

except Exception as e:
print(f"n?? 發生錯誤: {str(e)}")

async def cleanup(self):
"""清理資源"""
await self.exit_stack.aclose()

async def main():
client = MCPClient()
try:
await client.chat_loop()
finally:
await client.cleanup()

if __name__ == "__main__":
asyncio.run(main())

然后在文件夾中新建.env文件,寫入對應的api-key:
我測試過了,deepseek官網的api才支持后續的工具的使用,或者是昂貴的openai和claude,這里就不考慮了

BASE_URL=https://api.deepseek.com
MODEL=deepseek-chat
OPENAI_API_KEY="sk-xxx"

運行:

uv run client.py


然后是服務端的核心部分,我們以天氣調用的工具為例:
首先你需要一個openweather的API來查詢天氣:https://openweathermap.org/api

注冊一個賬號之后去生成一個API即可

服務端的依賴項安裝:

uv add mcp httpx

新建一個server.py:

以標準 I/O 方式運行 MCP 服務器

mcp.run(transport='stdio')
# 初始化 MCP 服務器
mcp = FastMCP("WeatherServer")

# OpenWeather API 配置
OPENWEATHER_API_BASE = "https://api.openweathermap.org/data/2.5/weather"
API_KEY = "xxx"

# 請替換為你自己的 OpenWeather API Key
USER_AGENT = "weather-app/1.0"

async def fetch_weather(city: str) -> dict[str, Any] | None:
"""
從 OpenWeather API 獲取天氣信息。
:param city: 城市名稱(需使用英文,如 Beijing)
:return: 天氣數據字典;若出錯返回包含 error 信息的字典
"""
params = {
"q": city,
"appid": API_KEY,
"units": "metric",
"lang": "zh_cn"
}
headers = {"User-[Agent](http://www.dlbhg.com/wiki/what-is-an-ai-agent/)": USER_AGENT}

async with httpx.AsyncClient() as client:
try:
response = await client.get(OPENWEATHER_API_BASE, params=params, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()

# 返回字典類型
except httpx.HTTPStatusError as e:
return {"error": f"HTTP 錯誤: {e.response.status_code}"}
except Exception as e:
return {"error": f"請求失敗: {str(e)}"}

def format_weather(data: dict[str, Any] | str) -> str:
"""
將天氣數據格式化為易讀文本。
:param data: 天氣數據(可以是字典或 JSON 字符串)
:return: 格式化后的天氣信息字符串
"""

# 如果傳入的是字符串,則先轉換為字典
if isinstance(data, str):
try:
data = json.loads(data)
except Exception as e:
return f"無法解析天氣數據: {e}"

# 如果數據中包含錯誤信息,直接返回錯誤提示
if"error"in data:
return f"?? {data['error']}"

# 提取數據時做容錯處理
city = data.get("name", "未知")
country = data.get("sys", {}).get("country", "未知")
temp = data.get("main", {}).get("temp", "N/A")
humidity = data.get("main", {}).get("humidity", "N/A")
wind_speed = data.get("wind", {}).get("speed", "N/A")

# weather 可能為空列表,因此用 [0] 前先提供默認字典
weather_list = data.get("weather", [{}])
description = weather_list[0].get("description", "未知")

return (
f"?? {city}, {country}n"
f"?? 溫度: {temp}°Cn"
f"?? 濕度: {humidity}%n"
f"?? 風速: {wind_speed} m/sn"
f"?? 天氣: {description}n"
)

@mcp.tool()
async def query_weather(city: str) -> str:
"""
輸入指定城市的英文名稱,返回今日天氣查詢結果。
:param city: 城市名稱(需使用英文)
:return: 格式化后的天氣信息
"""
data = await fetch_weather(city)
return format_weather(data)

if __name__ == "__main__":

# 以標準 I/O 方式運行 MCP 服務器
mcp.run(transport='stdio')

新的客戶端部分client_new.py:

if name == "main":
import sys
asyncio.run(main())

from openai import OpenAI
from dotenv import load_dotenv

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# 加載 .env 文件,確保 API Key 受到保護
load_dotenv()

class MCPClient:
def __init__(self):
"""初始化 MCP 客戶端"""
self.exit_stack = AsyncExitStack()
self.openai_api_key = os.getenv("OPENAI_API_KEY")

# 讀取 OpenAI API Key
self.base_url = os.getenv("BASE_URL")

# 讀取 BASE YRL
self.model = os.getenv("MODEL")

# 讀取 model
if not self.openai_api_key:
raise ValueError("? 未找到 OpenAI API Key,請在 .env 文件中設置 OPENAI_API_KEY")
self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url)

# 創建OpenAI client
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()

async def connect_to_server(self, server_script_path: str):
"""連接到 MCP 服務器并列出可用工具"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("服務器腳本必須是 .py 或 .js 文件")

command = "python"if is_python else"node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)

# 啟動 MCP 服務器并建立通信
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))

await self.session.initialize()

# 列出 MCP 服務器上的工具
response = await self.session.list_tools()
tools = response.tools
print("n已連接到服務器,支持以下工具:", [tool.name for tool in tools])

async def process_query(self, query: str) -> str:
"""
使用大模型處理查詢并調用可用的 MCP 工具 (Function Calling)
"""
print(11111)
messages = [{"role": "user", "content": query}]
print(2222)
response = await self.session.list_tools()
print(33333)
available_tools = [{
"type": "function",
"function": {
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
}
} for tool in response.tools]
print(available_tools)
print(44)
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
tools=available_tools
)
print(5555)

# 處理返回的內容
content = response.choices[0]
if content.finish_reason == "tool_calls":

# 如何是需要使用工具,就解析工具
tool_call = content.message.tool_calls[0]
tool_name = tool_call.function.name
tool_args = json.loads(tool_call.function.arguments)

# 執行工具
result = await self.session.call_tool(tool_name, tool_args)
print(f"nn[Calling tool {tool_name} with args {tool_args}]nn")

# 將模型返回的調用哪個工具數據和工具執行完成后的數據都存入messages中
messages.append(content.message.model_dump())
messages.append({
"role": "tool",
"content": result.content[0].text,
"tool_call_id": tool_call.id,
})

# 將上面的結果再返回給大模型用于生產最終的結果
response = self.client.chat.completions.create(
model=self.model,
messages=messages,
)
return response.choices[0].message.content

return content.message.content

# async def process_query(self, query: str) -> str:

# """調用 OpenAI API 處理用戶查詢"""

# messages = [{"role": "system", "content": "你是一個智能助手,幫助用戶回答問題。"},

# {"role": "user", "content": query}]

# try:

# # 調用 OpenAI API

# response = await asyncio.get_event_loop().run_in_executor(

# None,

# lambda: self.client.chat.completions.create(

# model=self.model,

# messages=messages

# )

# )

# return response.choices[0].message.content

# except Exception as e:

# return f"?? 調用 OpenAI API 時出錯: {str(e)}"

async def chat_loop(self):
"""運行交互式聊天循環"""
print("n?? MCP 客戶端已啟動!輸入 'quit' 退出")

while True:
try:
query = input("n你: ").strip()
if query.lower() == 'quit':
break

print("chat ing")

response = await self.process_query(query)

# 發送用戶輸入到 OpenAI API
print(f"n?? OpenAI: {response}")

except Exception as e:
print(f"n?? 發生錯誤: {str(e)}")

async def cleanup(self):
"""清理資源"""
await self.exit_stack.aclose()

async def main():
if len(sys.argv) < 2:
print("Usage: python client.py ")
sys.exit(1)

client = MCPClient()
try:
await client.connect_to_server(sys.argv[1])
await client.chat_loop()
finally:
await client.cleanup()

if __name__ == "__main__":
import sys
asyncio.run(main())

要么新啟動一個終端來運行server部分,需要重新進入虛擬環境.當然,uv也支持同時運行,所以可以直接運行:

uv run client_new.py server.py

最終效果:


文章轉載自: MCP客戶端與服務端初使用——讓deepseek調用查詢天氣的mcp來查詢天氣

熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
3000+提示詞助力AI大模型
和專業工程師共享工作效率翻倍的秘密
熱門推薦
一個賬號試用1000+ API
助力AI無縫鏈接物理世界 · 無需多次注冊
返回頂部
上一篇
如何使用 DeepSeek 構建 AI Agent:終極指南
最后一篇
国内精品久久久久影院日本,日本中文字幕视频,99久久精品99999久久,又粗又大又黄又硬又爽毛片
国产色一区二区| 午夜欧美视频在线观看| 亚洲品质自拍视频| 成人免费电影视频| 免费成人在线播放| 久久精品亚洲乱码伦伦中文| 国产成人啪免费观看软件 | 欧美一区二区久久久| 日韩二区三区在线观看| 日韩欧美高清在线| 色婷婷精品大在线视频| 久久午夜羞羞影院免费观看| 中文字幕免费不卡| 日韩不卡在线观看日韩不卡视频| 国产乱码精品1区2区3区| 一区二区三区四区高清精品免费观看| 6080国产精品一区二区| 成人av在线播放网址| 韩国v欧美v日本v亚洲v| 亚洲狠狠丁香婷婷综合久久久| 精品处破学生在线二十三| 6080日韩午夜伦伦午夜伦| 天堂影院一区二区| 538prom精品视频线放| 欧美日韩高清不卡| 欧美一区二区三级| 91麻豆精品91久久久久久清纯| 国产·精品毛片| 欧日韩精品视频| 色综合激情久久| 在线中文字幕一区二区| 在线电影院国产精品| 日韩三级av在线播放| 2欧美一区二区三区在线观看视频 337p粉嫩大胆噜噜噜噜噜91av | 日韩一区二区三区三四区视频在线观看| 91年精品国产| 51久久夜色精品国产麻豆| 国产视频在线观看一区二区三区| 国产丝袜美腿一区二区三区| 久久色在线视频| 国产精品久久久久影院色老大| 久久色在线视频| 五月激情丁香一区二区三区| 久久精品国产亚洲一区二区三区| 国产精品综合二区| 欧美一卡2卡三卡4卡5免费| 国产亚洲精品aa午夜观看| 亚洲欧美日本韩国| 国产精品18久久久| 日韩欧美亚洲国产另类| 日本免费新一区视频| 欧美亚洲日本国产| 亚洲人成伊人成综合网小说| 亚洲欧洲av一区二区三区久久| 亚洲成人高清在线| 成+人+亚洲+综合天堂| 亚洲精品一区在线观看| 国产精品久久久久久一区二区三区| 图片区日韩欧美亚洲| 一本大道久久精品懂色aⅴ| 亚洲国产成人在线| 亚洲高清一区二区三区| 在线免费观看日本欧美| 亚洲美女偷拍久久| 欧美日免费三级在线| 亚洲电影中文字幕在线观看| 麻豆一区二区在线| 日韩欧美国产1| 国产成人亚洲综合a∨婷婷| 中文字幕免费不卡| 欧美午夜不卡在线观看免费| 亚洲主播在线播放| 欧美tk丨vk视频| 色综合久久88色综合天天6 | 欧洲中文字幕精品| 美腿丝袜在线亚洲一区| 亚洲欧美日韩久久| 欧美经典一区二区三区| 一本大道久久a久久综合| 奇米精品一区二区三区在线观看| 中文字幕不卡在线播放| 日韩一区二区三区在线观看| 成人h版在线观看| 日本系列欧美系列| 亚洲激情六月丁香| 精品国产sm最大网站| 6080日韩午夜伦伦午夜伦| 国产在线精品一区二区三区不卡| 亚洲欧美乱综合| 国产精品美日韩| 久久综合视频网| 国产日韩v精品一区二区| 国产三级欧美三级日产三级99 | 综合亚洲深深色噜噜狠狠网站| 欧美成人激情免费网| 欧美人动与zoxxxx乱| 国产精品中文字幕欧美| 亚洲一区二区三区四区的| 亚洲蜜臀av乱码久久精品| 亚洲午夜视频在线| 国产一区不卡视频| 色88888久久久久久影院野外 | 欧美精品一区二区三区在线播放| 亚洲国产精品精华液ab| 亚洲国产成人av网| 国产高清久久久久| 欧美久久久一区| 国产精品污网站| 丝袜亚洲另类丝袜在线| 国产jizzjizz一区二区| 在线视频亚洲一区| 久久网这里都是精品| 欧美精品久久99| 欧美色图12p| 欧美三区在线视频| 日本韩国精品在线| 欧美三级欧美一级| 欧美日韩精品福利| 欧美在线|欧美| 欧美日韩日日摸| 亚洲精品一区二区三区影院| 国产三级精品在线| 精品综合久久久久久8888| 欧美一区二区精美| 日韩精品一二三四| 精品日韩一区二区三区| 免费高清在线一区| 欧美午夜精品一区二区三区| 亚洲国产精品久久一线不卡| jlzzjlzz欧美大全| 国产精品高清亚洲| 一本久久精品一区二区| 亚洲欧美日韩一区二区| 91色porny| 国产精品国产自产拍高清av王其| 国产99一区视频免费| 国产精品区一区二区三| 日本电影欧美片| 免费日韩伦理电影| 国产欧美中文在线| 91香蕉视频黄| 老司机精品视频导航| 欧美性极品少妇| 激情伊人五月天久久综合| 日韩美女视频一区二区| 日韩精品中午字幕| 国产一区二区三区四区五区美女 | 亚洲成av人片一区二区三区| 91精品国产综合久久久久久 | 欧美精品一二三区| 久久成人av少妇免费| 五月婷婷综合激情| 久久影院电视剧免费观看| 91麻豆国产香蕉久久精品| 国产精品国产三级国产aⅴ中文 | 国内精品不卡在线| 午夜日韩在线电影| 午夜日韩在线电影| 最新国产成人在线观看| 国产福利91精品一区二区三区| 国产精品人成在线观看免费| 6080国产精品一区二区| 欧美福利视频一区| 在线成人免费观看| 日韩一卡二卡三卡国产欧美| 欧美精选午夜久久久乱码6080| 欧美在线播放高清精品| 欧美日韩亚洲综合一区 | 国产成人免费在线观看不卡| 麻豆成人av在线| 国产成人在线网站| 中文av一区二区| 日av在线不卡| 国产丝袜在线精品| 精品国产一区二区精华| 国产清纯在线一区二区www| 久久综合色综合88| 亚洲视频小说图片| 日韩av二区在线播放| 久久99国产乱子伦精品免费| 国产精品白丝av| 欧美日本一道本| 精品理论电影在线观看| 亚洲精品视频在线观看免费| 国内精品久久久久影院色| 99在线精品视频| 精品国产网站在线观看| 亚洲视频资源在线| 另类小说一区二区三区| 成人avav影音| 日韩视频永久免费| 亚洲精品va在线观看| 大桥未久av一区二区三区中文| 欧美日韩免费在线视频| 亚洲欧美激情插| 91影院在线免费观看| 亚洲国产电影在线观看| 国产一区二区三区四| 欧美xxxxxxxxx| 激情综合亚洲精品|