《DeepSeek 原生应用与智能体开发实践》【摘要 书评 试读】- 京东图书
MCP作为一种具有开创性的开放协议,其核心目标在于标准化人工智能模型与外部数据源、工具之间的交互方式。在当今复杂多变的人工智能应用环境中,模型需要与各种不同类型的数据源和工具进行交互,以实现更加智能、高效的任务处理。通过MCP,大模型可以轻松地与各种专业工具进行连接和通信,无须进行复杂的接口开发和数据转换,从而大大提高了开发效率和应用效果。同时,MCP的标准化特性也保证了不同模型、不同工具之间的兼容性和互操作性,为人工智能技术的广泛应用和深入发展奠定了坚实的基础。
下面这个博文完成了本地MCP服务的搭建:
大模型在线MCP服务器搭建_pip install fastapi-mcp-CSDN博客
本文将完成一个MCP客户端程序,用于连接和使用在线MCP服务,代码如下:
import asyncio
import json
import logging
from mcp.client.session import ClientSession
from mcp.client.sse import sse_client
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# 工具描述转换器
def transform_tools(tools):
tool_list = []
for tool in tools:
parameters = {}
required = tool.inputSchema.get('required', [])
for name, prop in tool.inputSchema['properties'].items():
parameters[name] = {
'type': prop['type'],
'description': prop.get('description', ''),
'required': name in required
}
tool_list.append({
'name': tool.name,
'description': tool.description,
'parameters': parameters
})
return json.dumps(tool_list, ensure_ascii=False, indent=2)
from openai import OpenAI
def ask_llm_deepseek(question, tools_list):
# TODO: 实现与LLM的交互逻辑
# 这里只是一个示例,实际应用中需要根据具体情况进行实现
system_prompt = tools_list + '\n 根据以上描述,用户要求:%s ,请生成一个工具调用命令,要求以json格式输出{"tool":工具名,"tool_input":参数字典},只输出json,不要输出其他内容' % (
question)
client = OpenAI(
api_key="sk-282074c41d594514aee6fd6f179ed292",
base_url="https://api.deepseek.com/beta",
)
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": "Hello"},
],
max_tokens=1024,
temperature=0.99,
stream=False
)
generated_text = response.choices[0].message.content # 提取文本内容
return generated_text, client # 返回文本而非response对象
def llm_deepseek(question,client):
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "user", "content": question},
],
max_tokens=1024,
temperature=0.99,
stream=False
)
generated_text = response.choices[0].message.content # 提取文本内容
return generated_text
async def main(question = "25+38是多少?"):
async with sse_client("http://localhost:8000/mcp") as streams:
async with ClientSession(streams[0], streams[1]) as session:
await session.initialize()
# 获取工具列表
tools = (await session.list_tools()).tools
s = transform_tools(tools) +"\n"
response, client = ask_llm_deepseek(question, s)
# 清理Markdown标记
response = response.strip().replace(''''json', '').replace(''''', '').strip()
# print(response)
mtools = json.loads(response) # 现在response是纯JSON字符串
print("mtools: --> ",mtools)
if 'tool' in mtools:
tool_name = mtools['tool']
tool_input = mtools['tool_input']
# 调用工具
print("调用工具:", tool_name, tool_input)
ret = await session.call_tool(tool_name, tool_input)
if ret:
try:
r = json.loads(ret.content[0].text)
except:
r = ret.content[0].text
print("工具返回结果:", r)
questions = f"用户的问题是{question},根据{tool_name}的返回结果为:{r},根据以上信息,回答问题。"
r = llm_deepseek(questions,client)
return r
if __name__ == "__main__":
questions = ['计算一下356*125', '25+38是多少?', '现在的时间是什么时候?', 'Shanghai天气怎么样?', '请给我讲一个笑话']
for question in questions:
response = asyncio.run(main(question))
print(response)
print("--------------------------------------------------------")
先启动MCP服务,如下:
再运行本文完成的MCP客户端程序:
完整的运行结果如下:
C:\Users\xiayu\miniconda3\python.exe C:\Users\xiayu\PycharmProjects\DeepSeek应用开发实践-源码\第六章\6_2\demo_2.py
[07/01/25 14:16:20] INFO Processing request of type server.py:523
ListToolsRequest
[07/01/25 14:16:23] INFO Processing request of type server.py:523
CallToolRequest
mtools: --> {'tool': 'multiply_numbers', 'tool_input': {'a': 356, 'b': 125}}
调用工具: multiply_numbers {'a': 356, 'b': 125}
工具返回结果: 44500
根据用户提供的信息,计算 \(356 \times 125\) 的步骤如下:
1. **分解乘数**:
\(125\) 可以表示为 \(100 + 25\),因此:
\[
356 \times 125 = 356 \times (100 + 25)
\]
2. **分配律展开**:
\[
356 \times 100 = 35,\!600
\]
\[
356 \times 25 = 8,\!900 \quad (\text{因为 } 356 \times 25 = 356 \times \frac{100}{4} = 8,\!900)
\]
3. **相加得到结果**:
\[
35,\!600 + 8,\!900 = 44,\!500
\]
**最终答案**:
\[
\boxed{44500}
\]
[07/01/25 14:16:34] INFO Processing request of type server.py:523
ListToolsRequest
mtools: --> {'tool': 'add_numbers', 'tool_input': {'a': 25, 'b': 38}}
调用工具: add_numbers {'a': 25, 'b': 38}
工具返回结果: 63
[07/01/25 14:16:38] INFO Processing request of type server.py:523
CallToolRequest
25 + 38 的计算结果是 **63**。
[07/01/25 14:16:42] INFO Processing request of type server.py:523
ListToolsRequest
[07/01/25 14:16:46] INFO Processing request of type server.py:523
CallToolRequest
mtools: --> {'tool': 'date_time', 'tool_input': {}}
调用工具: date_time {}
工具返回结果: 2025-07-01 14:16:46
现在是2025年7月1日,下午2点16分46秒。
[07/01/25 14:16:50] INFO Processing request of type server.py:523
ListToolsRequest
[07/01/25 14:16:55] INFO Processing request of type server.py:523
CallToolRequest
mtools: --> {'tool': 'get_weather', 'tool_input': {'city_name': 'Shanghai'}}
调用工具: get_weather {'city_name': 'Shanghai'}
工具返回结果: {'城市': 'Shanghai', '温度': '23℃'}
上海的天气目前是23℃。
[07/01/25 14:16:59] INFO Processing request of type server.py:523
ListToolsRequest
mtools: --> {}
当然!这里有一个经典的笑话:
---
**病人**:医生,我最近总是觉得自己像一只猫。
**医生**:哦?这种情况持续多久了?
**病人**:喵……
(冷场两秒后)
**医生**:好吧,看来我们得从“汪”开始治疗了。
---
希望这个冷笑话能让你嘴角上扬! 😄 还想听别的类型吗?
Process finished with exit code 0