10分钟打造本地MCP服务:让AI调用你的一切工具
前言
MCP(Model Context Protocol,模型上下文协议)让 AI 能够调用外部工具。但市面上的 MCP Server 有限,如果你想让 AI 访问你本地的数据、脚本、文件,自建一个本地 MCP 就是最好的选择。
本文手把手教你在 10 分钟内搭建一个本地 MCP 服务,并对接到 QwenPaw(同样适用于 Claude Desktop、Cline 等 MCP 客户端)。
一、MCP 是什么?
MCP 是 Anthropic 在 2024 年底开源的协议标准,目标是让 AI 模型与外部工具之间的连接标准化。
你的 AI 应用 (QwenPaw / Claude Desktop / ...)
↕ MCP 协议
MCP Server (本地 / 远程)
↕
你的工具 (文件搜索、API 调用、本地脚本...)
只要实现了 MCP 协议,任何 AI 客户端都能无缝调用。
二、准备工作
1. Python 环境(推荐 3.10+)
python --version # 确认 >= 3.10
2. 创建项目目录
mkdir ~/my-mcp-server && cd ~/my-mcp-server
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
3. 安装依赖
pip install fastmcp python-dotenv requests
三、编写你的第一个 MCP 服务
这里用 文件搜索工具 作为示例——让 AI 能搜索本地指定目录下的文件。
创建文件 my_mcp.py:
"""
我的第一个本地 MCP 服务
功能:搜索本地文件、读取文件内容
"""
import os
from pathlib import Path
from fastmcp import FastMCP
# 创建 MCP 服务,名称随意
mcp = FastMCP("my-local-mcp")
# 搜索文件工具
@mcp.tool()
def search_files(directory: str, pattern: str, max_results: int = 20) -> dict:
"""
在指定目录下搜索包含关键词的文件
Args:
directory: 要搜索的目录路径
pattern: 文件名或扩展名关键词(如 ".py" 或 "config")
max_results: 最大返回数量
"""
path = Path(directory).expanduser().resolve()
if not path.exists():
return {"success": False, "error": f"目录不存在: {path}"}
results = []
for item in path.rglob(f"*{pattern}*"):
if item.is_file() and len(results) < max_results:
try:
size = item.stat().st_size
results.append({
"name": item.name,
"path": str(item),
"size": size,
"size_str": f"{size/1024:.1f} KB" if size > 1024 else f"{size} B"
})
except PermissionError:
continue
return {
"success": True,
"count": len(results),
"files": results
}
# 读取文件内容工具
@mcp.tool()
def read_file(file_path: str, max_lines: int = 100) -> dict:
"""
读取本地文件内容
Args:
file_path: 文件完整路径
max_lines: 最大读取行数
"""
path = Path(file_path).expanduser().resolve()
if not path.exists():
return {"success": False, "error": f"文件不存在: {path}"}
try:
with open(path, "r", encoding="utf-8") as f:
lines = [f.readline() for _ in range(max_lines)]
content = "".join(lines)
return {
"success": True,
"name": path.name,
"path": str(path),
"content": content,
"truncated": len(content) >= max_lines * 100
}
except Exception as e:
return {"success": False, "error": f"读取失败: {str(e)}"}
# ★★★ 关键:关闭欢迎 banner,避免污染 JSON-RPC 流 ★★★
if __name__ == "__main__":
mcp.run(show_banner=False)
⚠️
show_banner=False非常重要! FastMCP 默认会往 stdout 打印 ASCII banner,这会破坏 MCP 的 JSON-RPC 通信,导致客户端无法解析响应。务必加上。
四、测试 MCP 服务
在终端中发送 MCP 协议消息,验证服务是否正常:
cd ~/my-mcp-server
source .venv/bin/activate
# 发送 initialize + tools/list 请求
printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}\n{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}\n' \
| python my_mcp.py 2>/dev/null | grep '"name"'
正常情况下应该看到:
{"jsonrpc":"2.0","id":1,"result":{...}}
{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"search_files",...},{"name":"read_file",...}]}}
五、接入 QwenPaw
1. 修改 QwenPaw 配置
找到你的 QwenPaw 工作目录下的 agent.json,添加 MCP 客户端配置:
{
"mcp": {
"clients": {
"my_local_mcp": {
"name": "my_local_mcp",
"description": "本地文件搜索 MCP",
"enabled": true,
"transport": "stdio",
"command": "/Users/你的用户名/my-mcp-server/.venv/bin/python",
"args": ["/Users/你的用户名/my-mcp-server/my_mcp.py"],
"env": {}
}
}
}
}
2. 重启 QwenPaw
qwenpaw daemon restart
3. 验证
在 QwenPaw 中发送消息:
"请在 ~/Downloads 目录下搜索包含 '合同' 的文件"
如果返回了文件列表,说明 MCP 已经成功接入!
六、常见问题排查
Q1: MCP 连接成功但工具列表为空
原因: tools/list 请求前 MCP 服务崩溃了。
排查:
# 单独测试 initialize
printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}\n' \
| python my_mcp.py 2>&1 | head -5
如果看到 ASCII banner(╭──...)或大量无关输出,说明 show_banner 问题,把 mcp.run() 改成 mcp.run(show_banner=False)。
Q2: QwenPaw 日志显示 "lifecycle task exited"
原因: MCP 服务进程启动后立即退出。
排查:
python my_mcp.py # 前台运行,看是否有报错
Q3: ImportError: No module named 'fastmcp'
原因: Python 路径没有找到虚拟环境中的包。
排查: 确认 agent.json 中 command 指向的是 虚拟环境中的 Python,不是系统 Python。
Q4: Token 问题(调用外部 API 时)
在项目根目录创建 .env 文件:
echo 'API_KEY=your_api_key_here' >> .env
然后在 Python 中加载:
from dotenv import load_dotenv
load_dotenv()
import os
api_key = os.getenv("API_KEY", "")
七、进阶:更复杂的服务示例
调用本地脚本
@mcp.tool()
def run_script(script_path: str, args: str = "") -> dict:
"""执行本地 Python 脚本"""
import subprocess
result = subprocess.run(
f"python {script_path} {args}",
shell=True,
capture_output=True,
text=True,
timeout=60
)
return {
"success": result.returncode == 0,
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
}
数据库查询
@mcp.tool()
def query_db(sql: str) -> dict:
"""执行 SQLite 查询"""
import sqlite3
conn = sqlite3.connect("/path/to/your/database.db")
cur = conn.cursor()
try:
cur.execute(sql)
rows = cur.fetchall()
columns = [desc[0] for desc in cur.description] if cur.description else []
return {"success": True, "columns": columns, "rows": rows}
except Exception as e:
return {"success": False, "error": str(e)}
finally:
conn.close()
八、总结
| 步骤 | 核心操作 |
|---|---|
| 1 | pip install fastmcp |
| 2 | 用 @mcp.tool() 装饰器定义工具函数 |
| 3 | mcp.run(show_banner=False) 启动服务 |
| 4 | 在 QwenPaw agent.json 中添加客户端配置 |
| 5 | 重启 QwenPaw,开始使用 |
MCP 的强大之处在于,只要你能在 Python 里实现某个功能,AI 就能通过自然语言调用它。本地文件搜索、数据库查询、API 调用、脚本执行……一切皆可 MCP。
如果你觉得这篇文章有帮助,欢迎在博客园留言交流!

浙公网安备 33010602011771号