Model Context Protocol 是一个开放标准,它的目标是给 LLM 一种干净、统一的方式去发现和调用外部工具。不用再写自定义解析、不用再维护脆弱的胶水代码,就是一个好用的协议。
大多数 MCP 教程上来就讲 JSON-RPC 规范、传输层协议,搞得很复杂。其实用 MCP 不需要理解协议内部构造就像写 Web 应用不需要去读 HTTP 规范一样。
真正需要掌握的东西就三个概念,花 15 分钟就够了。
三个核心概念
MCP 的核心就三样东西:
Server:对外暴露工具的服务端,本质上是一个 Python 脚本,声明"这些函数可以被 LLM 调用",跑起来之后就在监听请求。
Tool:希望 LLM 使用的函数,可以是任何东西:查天气、查数据库、发邮件。这跟写普通 Python 函数没什么区别,加个装饰器剩下的交给 MCP。
Client:连接 Server 并调用工具的客户端。生产环境里一般就是 LLM 应用本身。测试阶段可以用 FastMCP 自带的客户端,开箱即用。
Server 暴露工具,Client 调用工具。就这么简单。
传输方式、JSON-RPC、能力协商这些都是实现细节,上生产之前不用管。
步骤 1:安装 FastMCP
FastMCP 是让 MCP 用起来简单的 Python 框架。装一下就行,不需要任何配置。
pip install fastmcp
本教程不需要虚拟环境,生产环境建议还是用一个。
步骤 2:创建 Server
新建一个 my_server.py 文件:
from fastmcp import FastMCP
# Initialize the server with a name
mcp = FastMCP("my-first-server")
# Define a tool using the @mcp.tool decorator
@mcp.tool
def get_weather(city: str) -> dict:
"""Get the current weather for a city."""
# In production, you'd call a real weather API
# For now, we'll return mock data
weather_data = {
"new york": {"temp": 72, "condition": "sunny"},
"london": {"temp": 59, "condition": "cloudy"},
"tokyo": {"temp": 68, "condition": "rainy"},
}
city_lower = city.lower()
if city_lower in weather_data:
return {"city": city, **weather_data[city_lower]}
else:
return {"city": city, "temp": 70, "condition": "unknown"}
# Run the server
if __name__ == "__main__":
mcp.run(transport="stdio")
FastMCP("my-first-server") 创建一个带名称的服务器实例。@mcp.tool 装饰器把普通函数注册为 MCP 工具。函数的 docstring 会变成工具描述——LLM 靠这个来判断什么时候该调用它。类型提示(city: str、-> dict)告诉 MCP 输入输出的类型。transport="stdio" 表示通过标准输入输出通信,本地测试够用了。
整个 Server 就这些,实际代码 15 行。
步骤 3:写个 Client 测试一下
新建 test_client.py:
import asyncio
from fastmcp import Client
async def main():
# Point the client at your server file
client = Client("my_server.py")
# Connect to the server
async with client:
# List available tools
tools = await client.list_tools()
print("Available tools:")
for tool in tools:
print(f" - {tool.name}: {tool.description}")
print("\n" + "="*50 + "\n")
# Call the weather tool
result = await client.call_tool(
"get_weather",
{"city": "Tokyo"}
)
print(f"Weather result: {result}")
if __name__ == "__main__":
asyncio.run(main())
Client("my_server.py") 指定要连接的 Server 文件;async with client: 自动管理连接生命周期;list_tools() 负责动态发现可用工具,这是 MCP 的核心能力之一;call_tool("get_weather", {"city": "Tokyo"}) 带参数调用具体工具。
步骤 4:跑起来
终端里执行:
python test_client.py
输出应该是这样的:
Available tools:
- get_weather: Get the current weather for a city.
==================================================Weather result: {'city': 'Tokyo', 'temp': 68, 'condition': 'rainy'}
到这里就完成了。一个 MCP Server 搭好了Client 也成功调用了它。
步骤 5:增加更多工具
MCP 真正好用的地方在于扩展成本极低,再往 Server 里再加两个工具:
from fastmcp import FastMCP
from datetime import datetime
mcp = FastMCP("my-first-server")
@mcp.tool
def get_weather(city: str) -> dict:
"""Get the current weather for a city."""
weather_data = {
"new york": {"temp": 72, "condition": "sunny"},
"london": {"temp": 59, "condition": "cloudy"},
"tokyo": {"temp": 68, "condition": "rainy"},
}
city_lower = city.lower()
if city_lower in weather_data:
return {"city": city, **weather_data[city_lower]}
return {"city": city, "temp": 70, "condition": "unknown"}
@mcp.tool
def get_time(timezone: str = "UTC") -> str:
"""Get the current time in a specified timezone."""
# Simplified - in production use pytz or zoneinfo
return f"Current time ({timezone}): {datetime.now().strftime('%H:%M:%S')}"
@mcp.tool
def calculate(expression: str) -> dict:
"""Safely evaluate a mathematical expression."""
try:
# Only allow safe math operations
allowed_chars = set("0123456789+-*/.() ")
if not all(c in allowed_chars for c in expression):
return {"error": "Invalid characters in expression"}
result = eval(expression) # Safe because we validated input
return {"expression": expression, "result": result}
except Exception as e:
return {"error": str(e)}
if __name__ == "__main__":
mcp.run(transport="stdio")
再跑一次测试客户端,三个工具全部自动发现:
Available tools:
- get_weather: Get the current weather for a city.
- get_time: Get the current time in a specified timezone.
- calculate: Safely evaluate a mathematical expression.
不需要改配置,不需要写路由。加了工具就直接可用。
最后:接入 LLM
前面写的 Client 是测试用的。生产环境里,LLM 框架本身充当 Client 角色。概念上大概是这样:
How MCP connects your LLM to external tools: the framework calls the client, which discovers and invokes tools from your server.
Server 端的代码完全不用动,这正是 MCP 的价值所在——工具写一次,任何兼容 MCP 的客户端都能用。
生产部署时需要把传输方式从 stdio 换成 http:
if __name__ == "__main__":
mcp.run(transport="http", host="0.0.0.0", port=8000)
这样 MCP Server 就以 HTTP 端点的形式对外暴露,远程客户端可以直接连接。
总结
现在你手头已经有一个能跑的 MCP Server 了,前后也就 15 分钟。下一步就是把它接到实际的 LLM 上,做点真正有用的东西出来。
https://avoid.overfit.cn/post/c9314c34543a4ed1a1bb15b92d1c6ca2
by Paolo Perrone
热门跟贴