用MCP实现一个简单的Client + Server计算工具
你是不是经常有这种想法:我写了个Python脚本,能不能让另一个脚本来远程调用它?又或者,我想写一个可以随时调用的小工具,别老每次都跑一堆代码……那你真的可以试试 MCP(Modular Communication Protocol)。它让你不用搞复杂的网络协议、服务部署啥的,就能让多个Python程序之间愉快“对话”。
而且我跟你说,真的超简单,连我这种不搞后端的都能一次性跑起来。这篇教程我就按最小白的方式,手把手带你从0到1,把一个“计算器服务”搭出来。你只要照着一步步来,肯定能搞定!
一、准备环境:安装MCP
只要你电脑上有 Python(建议版本 3.8+),第一步就是打开终端(Windows用CMD或者PowerShell,Mac/Linux直接Terminal)运行:
bashpip install mcp
这行命令会自动帮你把 MCP 所有需要的依赖装好。
装完以后,就可以开始写代码啦!
二、先写 MCP 服务端(Server)
我们先来做一个“服务端”,功能很简单:你告诉它一个数学表达式,它给你返回答案。
步骤1:新建一个文件,命名为 server_demo.py
用你喜欢的编辑器打开这个文件,比如 VSCode、PyCharm,或者直接用记事本也行。
然后复制下面这段代码进去:
python
# server_demo.py 修改版
import math
import re
from typing import Dict, List, Union, Optional
from mcp.server.fastmcp import FastMCP
# 创建一个 MCP 服务实例
mcp = FastMCP("高级计算器服务")
# 存储计算历史
calculation_history = []
@mcp.tool()
def calculate(expression: str) -> float:
"""
输入一个数学表达式,返回计算结果
例如:'1 + 2 * 3' => 7
"""
# 安全检查:只允许合法的数学表达式
if not is_safe_expression(expression):
return f"错误:不安全的表达式 '{expression}'"
try:
# 使用更安全的方式计算表达式
result = safe_eval(expression)
# 记录历史
calculation_history.append({"expression": expression, "result": result})
return float(result)
except Exception as e:
return f"计算错误: {str(e)}"
@mcp.tool()
def advanced_math(operation: str, value: float, second_value: Optional[float] = None) -> float:
"""
执行高级数学运算
参数:
- operation: 运算类型,可选值: 'sqrt'(平方根), 'pow'(幂), 'sin', 'cos', 'log'
- value: 要计算的数值
- second_value: 某些运算需要的第二个值(例如幂运算)
例如: advanced_math('sqrt', 16) => 4.0
"""
try:
if operation == 'sqrt':
if value < 0:
return "错误: 不能计算负数的平方根"
result = math.sqrt(value)
elif operation == 'pow':
if second_value is None:
return "错误: 幂运算需要提供第二个参数"
result = math.pow(value, second_value)
elif operation == 'sin':
result = math.sin(value)
elif operation == 'cos':
result = math.cos(value)
elif operation == 'log':
if value <= 0:
return "错误: 对数运算的值必须为正数"
if second_value is not None and second_value > 0:
result = math.log(value, second_value) # 自定义底数
else:
result = math.log(value) # 自然对数
else:
return f"错误: 不支持的运算 '{operation}'"
# 记录历史
calculation_history.append({
"operation": operation,
"value": value,
"second_value": second_value,
"result": result
})
return float(result)
except Exception as e:
return f"计算错误: {str(e)}"
@mcp.tool()
def get_calculation_history() -> List[Dict[str, Union[str, float]]]:
"""
获取计算历史记录
返回最近的计算历史列表
"""
return calculation_history[-10:] if calculation_history else []
@mcp.tool()
def clear_history() -> str:
"""
清除计算历史记录
"""
global calculation_history
calculation_history = []
return "历史记录已清除"
def is_safe_expression(expr: str) -> bool:
"""检查表达式是否安全,只允许基本数学运算"""
# 只允许数字、基本运算符和一些数学函数
allowed_pattern = r'^[\d\s\+\-\*\/\(\)\.\,\^\%]+$'
return bool(re.match(allowed_pattern, expr))
def safe_eval(expr: str) -> float:
"""更安全的表达式求值方法"""
# 替换幂运算符号为Python语法
expr = expr.replace('^', '**')
# 定义允许的数学函数和常量
safe_dict = {
'abs': abs,
'round': round,
'min': min,
'max': max,
'pi': math.pi,
'e': math.e
}
# 使用限制的命名空间计算表达式
return eval(expr, {"__builtins__": {}}, safe_dict)
# 启动 MCP Server - 修改为支持HTTP/WebSocket传输
if __name__ == "__main__":
import sys
if len(sys.argv) > 1 and sys.argv[1] == "--inspector":
# 当通过Inspector启动时,使用HTTP传输
mcp.run(transport='http', port=6275)
else:
# 默认使用stdio传输
mcp.run(transport='stdio')
是不是很简单?重点在 @mcp.tool()
这句,它会自动把 calculate
方法注册成 MCP 能识别的工具。客户端就可以远程调用这个函数了!
三、再写 MCP 客户端(Client)
客户端就是你启动去调用“服务端”的部分。
步骤2:新建另一个文件,叫 client_demo.py
复制下面的内容进去:
python
# client_demo.py
from mcp.client.stdio import stdio_client
from mcp import ClientSession, StdioServerParameters
import asyncio
import os
# 设置 Server 启动参数
server_params = StdioServerParameters(
command="python",
args=["./server_demo.py"], # 注意这里的路径要根据你自己保存的位置来改
env=None
)
async def main():
print("=== MCP 高级计算器客户端 ===")
print("正在连接到计算器服务...")
try:
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
print("连接成功!\n")
while True:
print("\n选择功能:")
print("1. 基本计算")
print("2. 高级数学运算")
print("3. 查看历史记录")
print("4. 清除历史记录")
print("0. 退出程序")
choice = input("\n请选择 (0-4): ")
if choice == '0':
print("谢谢使用,再见!")
break
elif choice == '1':
expression = input("\n请输入数学表达式 (例如: 2 + 3 * 4): ")
print(f"计算: {expression}")
try:
result = await session.call_tool("calculate", {"expression": expression})
print(f"结果: {result.content}")
except Exception as e:
print(f"调用出错: {e}")
elif choice == '2':
print("\n高级数学运算")
print("可用操作: sqrt(平方根), pow(幂), sin, cos, log")
operation = input("请输入操作类型: ")
try:
value = float(input("请输入第一个值: "))
second_value = None
if operation == 'pow' or operation == 'log':
second_value = float(input("请输入第二个值: "))
result = await session.call_tool(
"advanced_math",
{
"operation": operation,
"value": value,
"second_value": second_value
}
)
else:
result = await session.call_tool(
"advanced_math",
{
"operation": operation,
"value": value
}
)
print(f"结果: {result.content}")
except ValueError:
print("错误: 请输入有效的数字")
except Exception as e:
print(f"调用出错: {e}")
elif choice == '3':
try:
result = await session.call_tool("get_calculation_history", {})
history = result.content
if not history:
print("\n历史记录为空")
else:
print("\n=== 计算历史记录 ===")
for i, entry in enumerate(history, 1):
if "expression" in entry:
print(f"{i}. 表达式: {entry['expression']} = {entry['result']}")
else:
op_str = f"{entry['operation']}({entry['value']}"
if entry['second_value'] is not None:
op_str += f", {entry['second_value']}"
op_str += ")"
print(f"{i}. 高级运算: {op_str} = {entry['result']}")
except Exception as e:
print(f"获取历史记录失败: {e}")
elif choice == '4':
try:
result = await session.call_tool("clear_history", {})
print(result.content)
except Exception as e:
print(f"清除历史记录失败: {e}")
else:
print("无效的选择,请重试")
input("\n按回车键继续...")
# 清屏
os.system('cls' if os.name == 'nt' else 'clear')
except Exception as e:
print(f"连接服务器失败: {e}")
print("请确保 server_demo.py 文件路径正确,且已安装所有依赖")
# 运行主函数
if __name__ == "__main__":
asyncio.run(main())
这个脚本会自动调用 Server 并传一个表达式进去,然后返回结果。
四、开始运行:验证是否通了!
确保你现在这两个文件都写好了:
server_demo.py
client_demo.py
然后,直接在终端运行:
bashpython client_demo.py
是不是很神奇?你就会看到它打印:
发送表达式:188 * 23 - 34
结果是:4300.0
搞定!现在你已经成功用 MCP 连接了一个服务端和客户端,而且还完成了一次远程调用!
五、可视化调试 MCP Server(推荐!)
有时候你写完 Server 想先测试一下,不想写 Client,这时候 MCP 提供了一个调试神器:MCP Inspector。
首先我们先要先安装一下uv:
pip install uv
然后你在命令行里运行:
bashmcp dev server_demo.py
如果报错了:
Error: typer is required. Install with 'pip install mcp[cli]'
那么就先运行:
pip install mcp[cli]
然后浏览器打开:
http://localhost:6274
你就会进入一个超好用的界面,你可以直接点工具、填参数、点调用,看返回结果。
开发调试都超方便!
最后
我一开始以为搞客户端和服务端通讯会特别麻烦,得写 socket、搞接口、处理协议啥的,但用了 MCP 才发现,原来都帮你封装好了,连 transport 都默认支持 stdio。写起来像写普通 Python 脚本一样轻松,最适合做一些自动化工具、AI插件,甚至插件市场那种轻服务都可以搞一搞。
MCP 真的是一个小而美的协议框架,你动手写一遍就懂了。而且文档和调试工具都还挺友好的,不会让人踩坑。