之前写过一篇LM studio本地部署模型的文章,可以参考实现本地模型的部署或者是使用其他方式
文章链接: LM Studio本地部署大模型-CSDN博客
MCP(Model Context Protocol,模型上下文协议)是由Anthropic公司推出的开放标准协议,旨在为大型语言模型(LLM)与外部数据源、工具及服务提供统一的通信框架
MCP主机:发起请求的应用(如Claude Desktop)。
MCP客户端:负责与服务器通信。
MCP服务器:提供资源(如数据库)、工具(如API调用)和提示模板 。
LM studio本身并不支持mcp,我看有一些其他的本地部署工具是支持的,不过也看模型,因此局限性是有的,所以我们就还用lmstudio,Lm studio提供了兼容openai的接口,因此我们可以使用langchain+openai+mcp来轻松实现本地模型集成mcp
此处实现一个简单的mcp服务端用来做数学计算, 注意注释部分一定要明确工具的功能,否则模型是不会调用用具计算的
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("数学计算")
@mcp.tool("加法")
def add(a: int, b: int) -> int:
"""计算两个数的和,适用于需要精确加法运算的场景。示例:输入3和5返回8"""
return a + b
@mcp.tool("乘法")
def multiply(a: int, b: int) -> int:
"""计算两个数的乘积,适用于需要精确乘法运算的场景。示例:输入2和5返回10"""
return a * b
if __name__ == "__main__":
mcp.run(transport="stdio")
import asyncio
from langchain_core.load import dumps
from langchain_mcp_adapters.tools import load_mcp_tools
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
"""
主函数,用于初始化模型、服务器参数,并通过异步会话与服务器进行交互,最终获取并打印代理的响应。
该函数执行以下步骤:
1. 初始化ChatOpenAI模型,指定基础URL和模型名称。
2. 配置服务器参数,指定命令和参数。
3. 通过stdio_client与服务器建立连接,并创建会话。
4. 加载MCP工具并创建反应代理。
5. 向代理发送消息并获取响应,最后将响应以JSON格式打印出来。
"""
# 初始化ChatOpenAI模型,指定基础URL和模型名称
model = ChatOpenAI(base_url='http://127.0.0.1:1234/v1', model='qwen2.5-7b-instruct-1m')
# 配置服务器参数,指定命令和参数
server_params = StdioServerParameters(
command="python",
args=["math_server.py"],
)
# 通过stdio_client与服务器建立连接,并创建会话
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
# 初始化会话
await session.initialize()
# 加载MCP工具并创建反应代理
tools = await load_mcp_tools(session)
agent = create_react_agent(model, tools)
# 向代理发送消息并获取响应,最后将响应以JSON格式打印出来
agent_response = await agent.ainvoke({"messages": "(3 + 5) x 12等于多少?"})
json_str = dumps(agent_response, pretty=True, ensure_ascii=False)
print(json_str)
if __name__ == "__main__":
asyncio.run(main())
{
"messages": [
{
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"HumanMessage"
],
"kwargs": {
"content": "(3 + 5) x 12等于多少?",
"type": "human",
"id": "17e5ba57-bb0a-4f49-8321-5b2f8d81a85c"
}
},
{
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"AIMessage"
],
"kwargs": {
"content": "",
"additional_kwargs": {
"tool_calls": [
{
"id": "774037770",
"function": {
"arguments": "{\"a\":3,\"b\":5}",
"name": "加法"
},
"type": "function"
}
],
"refusal": null
},
"response_metadata": {
"token_usage": {
"completion_tokens": 61,
"prompt_tokens": 285,
"total_tokens": 346,
"completion_tokens_details": null,
"prompt_tokens_details": null
},
"model_name": "qwen2.5-7b-instruct-1m@q4_k_m",
"system_fingerprint": "qwen2.5-7b-instruct-1m@q4_k_m",
"id": "chatcmpl-b9dyxztbiydp2j814hpf2i",
"finish_reason": "tool_calls",
"logprobs": null
},
"type": "ai",
"id": "run-85702367-d8d0-4d3a-9453-d08cea063956-0",
"tool_calls": [
{
"name": "加法",
"args": {
"a": 3,
"b": 5
},
"id": "774037770",
"type": "tool_call"
}
],
"usage_metadata": {
"input_tokens": 285,
"output_tokens": 61,
"total_tokens": 346,
"input_token_details": {},
"output_token_details": {}
},
"invalid_tool_calls": []
}
},
{
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"ToolMessage"
],
"kwargs": {
"content": "8",
"type": "tool",
"name": "加法",
"id": "0d617d60-2cb0-48f1-adf2-c86d8e0f0918",
"tool_call_id": "774037770",
"status": "success"
}
},
{
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"AIMessage"
],
"kwargs": {
"content": "",
"additional_kwargs": {
"tool_calls": [
{
"id": "700353500",
"function": {
"arguments": "{\"a\":8,\"b\":12}",
"name": "乘法"
},
"type": "function"
}
],
"refusal": null
},
"response_metadata": {
"token_usage": {
"completion_tokens": 26,
"prompt_tokens": 330,
"total_tokens": 356,
"completion_tokens_details": null,
"prompt_tokens_details": null
},
"model_name": "qwen2.5-7b-instruct-1m@q4_k_m",
"system_fingerprint": "qwen2.5-7b-instruct-1m@q4_k_m",
"id": "chatcmpl-qd3fv1v1ysd4wp0wrikoam",
"finish_reason": "tool_calls",
"logprobs": null
},
"type": "ai",
"id": "run-8ad0b37b-8116-4491-bbc7-122d24893cdb-0",
"tool_calls": [
{
"name": "乘法",
"args": {
"a": 8,
"b": 12
},
"id": "700353500",
"type": "tool_call"
}
],
"usage_metadata": {
"input_tokens": 330,
"output_tokens": 26,
"total_tokens": 356,
"input_token_details": {},
"output_token_details": {}
},
"invalid_tool_calls": []
}
},
{
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"ToolMessage"
],
"kwargs": {
"content": "96",
"type": "tool",
"name": "乘法",
"id": "4bfb8eed-94ef-4717-8334-f2339ef721b1",
"tool_call_id": "700353500",
"status": "success"
}
},
{
"lc": 1,
"type": "constructor",
"id": [
"langchain",
"schema",
"messages",
"AIMessage"
],
"kwargs": {
"content": "(3 + 5) x 12 equals 96.",
"additional_kwargs": {
"refusal": null
},
"response_metadata": {
"token_usage": {
"completion_tokens": 15,
"prompt_tokens": 377,
"total_tokens": 392,
"completion_tokens_details": null,
"prompt_tokens_details": null
},
"model_name": "qwen2.5-7b-instruct-1m@q4_k_m",
"system_fingerprint": "qwen2.5-7b-instruct-1m@q4_k_m",
"id": "chatcmpl-3728wwge3n116qxfcy92sg",
"finish_reason": "stop",
"logprobs": null
},
"type": "ai",
"id": "run-184fd050-5d46-487c-8d4c-0ab7626a5aa2-0",
"usage_metadata": {
"input_tokens": 377,
"output_tokens": 15,
"total_tokens": 392,
"input_token_details": {},
"output_token_details": {}
},
"tool_calls": [],
"invalid_tool_calls": []
}
}
]
}
从控制台日志能知道一共进行了三次调佣
对模型进行提问
模型调用加法工具
模型调用乘法工具
这只是mcp最简单的一个实现, 现在已经有很多成熟的mcp-server,功能更为强大, 其基本原理还是通过模型来代人来调用某个工具, 经过上述实例, 我们也发现对于mcp-server工具的描述一定要准确, 否则模型无法识别都提供了哪些工具, 有了这种标准协议或许我们以后的模型部署不再需要大而全, 经过简单配置或许我们就实现了模型之间的相互调用,专业的模型干专业的事,实现分布式部署且能力也不差