MCP协议实战:Python开发首个AI工具服务
MCP协议赋予AI应用调用工具、读写数据等能力。文章介绍其核心概念、三大能力及stdio与SSE两种通信方式,并完整演示基于Python开发MCPServer的流程,涵盖环境搭建、工具实现及安全沙箱控制,为构建企业级AI工具服务提供实践参考。
大型语言模型的能力正在被赋予“双手”——借助MCP协议,AI应用如今能够真正执行代码、调用API、操作文件,而不仅仅是生成文本。本文将从零开始,完整呈现一个MCP Server的实战开发全流程,帮助你快速上手这一关键技术。
一、MCP协议是什么?
1.1 核心概念
MCP(Model Context Protocol)定义了一套标准化协议,让AI应用(Host)能够通过统一接口访问外部工具与数据资源。这套架构初看似乎复杂,但拆解后其实脉络清晰:AI应用作为主机,中间层是MCP客户端,最外层是MCP服务端,三者通过标准化的通信管道协同工作。

从架构全景图可以看出,MCP服务端主要提供三类核心能力:Tools(工具调用)、Resources(数据读取)和Prompts(提示模板)。Host内部的MCP客户端如同一位翻译官,负责在AI应用与服务端之间高效传递消息。
1.2 MCP三大核心能力
| 能力 | 说明 | 示例 |
|---|---|---|
| Tools | AI可调用的函数 | 查询数据库、调用API、执行计算 |
| Resources | AI可读取的数据源 | 文件内容、数据库记录、日志 |
| Prompts | 可复用的提示模板 | 代码审查模板、文档生成模板 |
1.3 通信方式
目前支持两种传输方式,如何选择?看场景。本地开发时,stdio模式最为直接,AI应用将MCP Server作为子进程启动,通过标准输入输出通信。远程部署则采用SSE(Server-Sent Events),即通过HTTP进行网络通信。两种方式各有优势:本地开发追求便捷,生产环境则必须依赖SSE。
方式一: stdio(标准输入输出)
┌──────────┐ stdin/stdout ┌──────────┐
│ AI 应用 │◄──────────────►│MCP Server│
│ (Host) │ │(子进程) │
└──────────┘ └──────────┘
方式二: SSE(Server-Sent Events)
┌──────────┐ HTTP + SSE ┌──────────┐
│ AI 应用 │◄──────────────►│MCP Server│
│ (Host) │ (网络通信) │(远程服务)│
└──────────┘ └──────────┘
二、开发环境搭建
2.1 安装依赖
先安装依赖包:pip install "mcp[cli]" httpx,一条命令即可完成。httpx作为异步HTTP客户端,用于替代requests,后续天气查询功能会用到它。
2.2 验证安装
执行 mcp --version,若能看到版本号,则说明安装成功。
2.3 项目结构
推荐的项目组织方式如下:
my-mcp-server/
├── server.py # MCP Server主文件
├── tools/
│ ├── weather.py # 天气查询工具
│ ├── database.py # 数据库查询工具
│ └── calculator.py # 计算器工具
├── resources/
│ └── system_info.py # 系统信息资源
├── prompts/
│ └── code_review.py # 代码审查提示模板
├── pyproject.toml # 项目配置
└── README.md
按功能模块拆分的好处在于:每个文件职责明确,后期维护时无需面对一个数千行的庞然大物,显著提升可维护性。
三、第一个MCP Server(快速上手)
3.1 最简实现
先从一个最简单的示例入手,感受MCP的魅力:
# server.py
from mcp.server.fastmcp import FastMCP
# 创建MCP Server实例
mcp = FastMCP(
name="my-first-mcp-server",
version="1.0.0",
)
@mcp.tool()
def add(a: int, b: int) -> int:
"""两个数字相加"""
return a + b
@mcp.tool()
def get_current_time(timezone: str = "Asia/Shanghai") -> str:
"""获取当前时间
Args:
timezone: 时区名称,默认为Asia/Shanghai
"""
from datetime import datetime
import pytz
tz = pytz.timezone(timezone)
now = datetime.now(tz)
return now.strftime("%Y-%m-%d %H:%M:%S %Z")
if __name__ == "__main__":
mcp.run()
注意到 @mcp.tool() 这个装饰器了吗?它正是将普通Python函数转变为AI可调用工具的关键标识。参数类型标注与docstring并非摆设——AI正是依赖这些信息来理解工具的正确使用方式。
3.2 运行测试
两种启动方式可供选择:
mcp dev server.py 会启动一个可视化调试工具(MCP Inspector),在浏览器中即可测试你的工具。或者直接运行 python server.py 也能正常启动。
四、实战:开发完整的企业工具服务
接下来进入干货环节,构建一个实用的MCP Server,涵盖天气查询、数据库操作、文件管理等核心功能。
4.1 天气查询工具
通过调用OpenWeatherMap API,支持当前天气与天气预报:
# tools/weather.py
import httpx
from mcp.server.fastmcp import tool
BASE_URL = "https://api.openweathermap.org/data/2.5"
@tool()
async def get_weather(city: str, api_key: str = "") -> str:
"""查询指定城市的当前天气信息
Args:
city: 城市名称(中文或英文),如"北京"或"Beijing"
api_key: OpenWeatherMap API Key(可选,默认使用内置测试key)
"""
params = {
"q": city,
"appid": api_key,
"units": "metric",
"lang": "zh_cn",
}
async with httpx.AsyncClient() as client:
resp = await client.get(f"{BASE_URL}/weather", params=params)
data = resp.json()
if resp.status_code != 200:
return f"查询失败: {data.get('message', '未知错误')}"
return (
f"【{data['name']} 天气】\n"
f"天气: {data['weather'][0]['description']}\n"
f"温度: {data['main']['temp']}°C (体感 {data['main']['feels_like']}°C)\n"
f"湿度: {data['main']['humidity']}%\n"
f"风速: {data['wind']['speed']} m/s"
)
@tool()
async def get_forecast(city: str, days: int = 3, api_key: str = "") -> str:
"""查询未来几天的天气预报
Args:
city: 城市名称
days: 预报天数(最多5天)
api_key: OpenWeatherMap API Key
"""
params = {
"q": city,
"appid": api_key,
"units": "metric",
"lang": "zh_cn",
"cnt": min(days, 5) * 8, # 每天约8个数据点
}
async with httpx.AsyncClient() as client:
resp = await client.get(f"{BASE_URL}/forecast", params=params)
data = resp.json()
forecasts = []
for item in data["list"][::8]: # 每天取一个数据点
forecasts.append(
f"{item['dt_txt'][:10]}: "
f"{item['weather'][0]['description']}, "
f"{item['main']['temp']}°C"
)
return f"【{data['city']['name']} 未来天气预报】\n" + "\n".join(forecasts)
4.2 SQLite数据库查询工具
本工具的设计重点在于安全性——仅允许SELECT操作,防止AI意外执行危险命令:
# tools/database.py
import sqlite3
from pathlib import Path
from mcp.server.fastmcp import tool
DB_PATH = Path("./data/app.db")
def _get_connection():
"""获取数据库连接"""
DB_PATH.parent.mkdir(exist_ok=True)
return sqlite3.connect(str(DB_PATH))
@tool()
def query_database(sql: str) -> str:
"""执行SQL查询语句(仅支持SELECT)
Args:
sql: SQL查询语句,仅允许SELECT操作
"""
# 安全检查:只允许SELECT
normalized = sql.strip().upper()
if not normalized.startswith("SELECT"):
return "错误:仅支持SELECT查询,不允许修改数据"
try:
conn = _get_connection()
cursor = conn.execute(sql)
columns = [desc[0] for desc in cursor.description]
rows = cursor.fetchall()
conn.close()
if not rows:
return "查询结果为空"
header = "| " + " | ".join(columns) + " |"
separator = "| " + " | ".join(["---"] * len(columns)) + " |"
data_rows = []
for row in rows[:50]: # 最多返回50行
data_rows.append("| " + " | ".join(str(v) for v in row) + " |")
table = "\n".join([header, separator] + data_rows)
return f"查询返回 {len(rows)} 行:\n{table}"
except Exception as e:
return f"查询出错: {str(e)}"
@tool()
def list_tables() -> str:
"""列出数据库中的所有表及其结构"""
conn = _get_connection()
cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = cursor.fetchall()
conn.close()
if not tables:
return "数据库为空,暂无表"
result = []
for (table_name,) in tables:
result.append(f"- **{table_name}**")
return "数据库中的表:\n" + "\n".join(result)
4.3 文件管理工具
文件操作最需防范路径穿越攻击,因此需要设置严格的沙箱限制:
# tools/file_manager.py
import os
from pathlib import Path
from mcp.server.fastmcp import tool
SAFE_DIR = Path("./data/workspace") # 安全沙箱目录
def _safe_path(filepath: str) -> Path:
"""确保文件路径在安全目录内"""
full_path = (SAFE_DIR / filepath).resolve()
if not str(full_path).startswith(str(SAFE_DIR.resolve())):
raise ValueError("路径超出安全范围")
return full_path
@tool()
def read_file(filepath: str) -> str:
"""读取文件内容
Args:
filepath: 相对于工作目录的文件路径
"""
path = _safe_path(filepath)
if not path.exists():
return f"文件不存在: {filepath}"
return path.read_text(encoding="utf-8")
@tool()
def write_file(filepath: str, content: str) -> str:
"""写入文件内容
Args:
filepath: 相对于工作目录的文件路径
content: 要写入的内容
"""
path = _safe_path(filepath)
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
return f"文件写入成功: {filepath} ({len(content)} 字符)"
@tool()
def list_files(directory: str = ".") -> str:
"""列出目录下的文件
Args:
directory: 相对于工作目录的目录路径
"""
path = _safe_path(directory)
if not path.exists():
return f"目录不存在: {directory}"
items = []
for item in sorted(path.iterdir()):
if item.is_dir():
items.append(f"
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
MyShell发布开源AI语音克隆工具OpenVoice,瞄准语音模仿领域
MyShell最新推出的开源语音克隆工具OpenVoice引起了广泛关注。这一创新产品由麻省理工学院(MIT)、清华大学以及加拿大人工智能初创公司MyShell合作开发。OpenVoice采用了一种概念简单但高效的方法,可几乎即时克隆用户的语音,并使用明显更少的计算资源。该工具不仅具备语音克隆的基本
Open Voice:轻松克隆任何声音,免费开源的AI语音克隆项目
Open Voice是由MyShell推出的一个免费开源的AI即时语音克隆项目,相较于其他的语音克隆技术,OpenVoice的优势在于仅需一段简短的音频,便能以惊人的准确度复刻说话者的音色,创造出让人信以为真的自然语音。除开复制和参考说话者的音色之外,OpenVoice还可以对语音风格进行精细控制,
VoiceCanvas-AI语音克隆 & TTS工具 | 40+种语言语音合成
VoiceCanvas是什么?VoiceCanvas是由先进AI驱动的语音克隆与文本转语音工具,支持40+种语言的即时语音合成。其核心能力包括:高质量语音合成:具有自然语调和节奏的清晰人声个性化语音克隆:通过3-10秒语音样本创建专属AI声纹多语言支持:覆盖全球主流语种的男 女声选择进阶调控功能:语
Github爆火AI语音克隆项目OpenVoice,精准进行声音复刻
最近,Github上的一个名为OpenVoice的AI语音克隆项目爆火,该项目由myshell-ai开源,仅开源了不到三周,就有了6 1k的star。OpenVoice仅需参考说话者的短音频片段,即可复制其声音并生成多种语言的语音。这一技术不仅实现了对音色的准确克隆,还在语音生成过程中提供了对情感、
Free Voice Cloning-免费AI语音克隆工具 | 5秒生成你的数字声音
Free Voice Cloning,一款真正0成本、无限制、跨语言的高质量AI语音克隆平台。适合内容创作者、教育者、AI开发者、播客人群等所有想要“复制自己的声音”并进行语音合成的用户。?️ Free Voice Cloning 是什么?Free Voice Cloning 是一个基于先进AI语音
- 热门数据榜
相关攻略
2026-07-14 17:32
2026-07-14 17:30
2026-07-14 17:30
2026-07-14 17:27
2026-07-14 17:27
2026-07-14 16:20
2026-07-14 16:19
2026-07-14 16:19
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

