MCP Server 开发实战:从零构建第一个 MCP 服务器
摘要:本文以实战为导向,手把手带你从零构建一个功能完整的 MCP Server。涵盖开发环境搭建、SDK 详解、工具/资源/提示模板的定义与暴露,以及测试调试技巧。所有代码均基于官方 Python SDK,可直接运行。
一、前言
MCP Server 是整个 MCP 生态的基石。每一个 MCP Server 都是一个轻量级的服务进程,它将特定领域能力(如数据库查询、API 调用、文件操作)封装为标准化的工具,供 LLM 应用调用。
截至 2026 年 7 月,MCP 官方 Registry 已收录近 9,652 个 Server,覆盖了从文件系统、Git、数据库到 Slack、Notion 等几乎所有主流工具和服务。但理解 MCP Server 的最佳方式,仍然是自己动手写一个。
本文将构建一个“开发助手” MCP Server,它提供以下能力:
- 工具:代码格式化、JSON 校验、正则表达式测试
- 资源:常用代码片段库
- 提示模板:代码审查模板
二、开发环境搭建
2.1 Python 环境要求
MCP Python SDK 要求 Python 3.10+,推荐使用虚拟环境:
# 创建虚拟环境python-mvenv mcp-dev-envsourcemcp-dev-env/bin/activate# Linux/macOS# mcp-dev-env\Scripts\activate # Windows# 安装 MCP SDKpipinstallmcp# 安装开发依赖(可选)pipinstallruff mypy pytest2.2 项目结构
dev-assistant-mcp/ ├── pyproject.toml # 项目配置 ├── src/ │ └── dev_assistant/ │ ├── __init__.py │ ├── server.py # MCP Server 主入口 │ ├── tools/ # 工具实现 │ │ ├── __init__.py │ │ ├── formatter.py │ │ ├── json_validator.py │ │ └── regex_tester.py │ ├── resources/ # 资源实现 │ │ ├── __init__.py │ │ └── snippets.py │ └── prompts/ # 提示模板 │ ├── __init__.py │ └── code_review.py └── tests/ └── test_server.py2.3 pyproject.toml 配置
[project] name = "dev-assistant-mcp" version = "0.1.0" description = "一个面向开发者的 MCP Server 工具集" requires-python = ">=3.10" dependencies = [ "mcp>=1.0.0", ] [project.scripts] dev-assistant = "dev_assistant.server:main"三、Server SDK 详解
3.1 FastMCP vs 低层 Server
MCP Python SDK 提供了两种构建 Server 的方式:
| 方式 | 特点 | 适用场景 |
|---|---|---|
| FastMCP | 高层封装,装饰器驱动 | 大多数场景,开发效率高 |
| 低层 Server | 完全控制协议细节 | 需要精细控制的高级场景 |
本文使用 FastMCP,它是目前推荐的开发方式。
3.2 FastMCP 核心 API
frommcp.server.fastmcpimportFastMCP# 创建 Server 实例mcp=FastMCP(name="my-server",# Server 名称instructions="使用说明",# 可选,帮助 LLM 理解如何使用)# 注册工具@mcp.tool()defmy_tool(param:str)->str:"""工具描述(会被 LLM 读取)"""return"result"# 注册资源@mcp.resource("my-resource://data")defmy_resource()->str:"""资源描述"""return"resource data"# 注册提示模板@mcp.prompt()defmy_prompt(topic:str)->str:"""提示模板描述"""returnf"请分析以下主题:{topic}"# 启动 Servermcp.run(transport="stdio")四、工具定义与暴露
4.1 代码格式化工具
# src/dev_assistant/tools/formatter.py# 代码格式化工具 —— 支持 Python 代码的自动格式化importsubprocessimporttempfileimportosfrommcp.server.fastmcpimportFastMCPdefregister_formatter_tools(mcp:FastMCP):"""注册代码格式化相关的 MCP 工具"""@mcp.tool()defformat_python_code(code:str,style:str="pep8")->str:""" 格式化 Python 代码。 将输入的 Python 代码按照指定风格进行自动格式化。 支持 PEP8、Black 等主流风格。 Args: code: 待格式化的 Python 代码字符串 style: 格式风格,可选 "pep8" 或 "black" Returns: 格式化后的代码字符串,或错误信息 """# 将代码写入临时文件withtempfile.NamedTemporaryFile(mode='w',suffix='.py',delete=False)asf:f.write(code)temp_path=f.nametry:ifstyle=="black":# 使用 Black 格式化器result=subprocess.run(["python","-m","black","--quiet",temp_path],capture_output=True,text=True,timeout=30)else:# 使用 autopep8 格式化器(默认)result=subprocess.run(["python","-m","autopep8","--in-place",temp_path],capture_output=True,text=True,timeout=30)ifresult.returncode!=0:returnf"格式化失败:{result.stderr}"# 读取格式化后的代码withopen(temp_path,'r')asf:formatted_code=f.read()returnformatted_codeexceptsubprocess.TimeoutExpired:return"格式化超时(30秒限制)"exceptFileNotFoundError:returnf"未找到格式化工具,请安装: pip install{style}"finally:# 清理临时文件os.unlink(temp_path)代码解读:
@mcp.tool()装饰器自动将函数签名和 docstring 转换为 JSON SchemaArgs和Returns部分会成为工具描述的一部分,帮助 LLM 理解如何使用- 使用
subprocess调用外部工具,通过临时文件实现代码传递 - 完善的错误处理确保 Server 不会因工具执行失败而崩溃
4.2 JSON 校验工具
# src/dev_assistant/tools/json_validator.py# JSON 校验工具 —— 校验 JSON 格式并可选地验证 SchemaimportjsonfromtypingimportOptionalfrommcp.server.fastmcpimportFastMCPdefregister_json_tools(mcp:FastMCP):"""注册 JSON 相关的 MCP 工具"""@mcp.tool()defvalidate_json(json_string:str,schema:Optional[str]=None)->str:""" 校验 JSON 字符串的格式正确性。 可选地验证 JSON 是否符合指定的 JSON Schema。 Args: json_string: 待校验的 JSON 字符串 schema: 可选的 JSON Schema 字符串,用于验证数据结构 Returns: 校验结果描述 """# 第一步: 基础 JSON 格式校验try:data=json.loads(json_string)exceptjson.JSONDecodeErrorase:return(f"❌ JSON 格式错误\n"f"位置: 第{e.lineno}行, 第{e.colno}列\n"f"错误:{e.msg}")# 第二步: 如果提供了 Schema,进行 Schema 校验ifschema:try:importjsonschema schema_obj=json.loads(schema)jsonschema.validate(instance=data,schema=schema_obj)returnf"✅ JSON 格式正确,且符合 Schema 规范\n数据类型:{type(data).__name__}"exceptjsonschema.ValidationErrorase:returnf"❌ Schema 校验失败:{e.message}"exceptImportError:return"⚠️ JSON 格式正确,但未安装 jsonschema 库(pip install jsonschema)"exceptjson.JSONDecodeError:return"❌ Schema 字符串不是有效的 JSON"returnf"✅ JSON 格式正确\n数据类型:{type(data).__name__}\n键数量:{len(data)ifisinstance(data,dict)else'N/A'}"代码解读:
Optional[str]类型标注使得schema参数成为可选参数,SDK 会自动在 Schema 中将其标记为非必需- 使用
jsonschema库进行可选的 Schema 验证,通过ImportError处理库未安装的情况 - 返回结构化的结果字符串,包含 emoji 标识和详细信息,便于 LLM 理解
五、资源与 Prompt 暴露
5.1 代码片段资源
# src/dev_assistant/resources/snippets.py# 代码片段资源 —— 提供常用代码模板frommcp.server.fastmcpimportFastMCP# 模拟的代码片段数据库SNIPPETS={"python/singleton":{"name":"Python 单例模式","language":"python","code":'''class Singleton: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance '''},"python/retry":{"name":"Python 重试装饰器","language":"python","code":'''import time from functools import wraps def retry(max_attempts=3, delay=1): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): for attempt in range(max_attempts): try: return func(*args, **kwargs) except Exception as e: if attempt == max_attempts - 1: raise time.sleep(delay * (2 ** attempt)) return wrapper return decorator '''},"python/context_manager":{"name":"Python 上下文管理器","language":"python","code":'''from contextlib import contextmanager @contextmanager def managed_resource(name): print(f"获取资源: {name}") try: yield name finally: print(f"释放资源: {name}") '''}}defregister_snippet_resources(mcp:FastMCP):"""注册代码片段资源"""@mcp.resource("snippets://library")deflist_snippets()->str:"""列出所有可用的代码片段"""result="📚 代码片段库\n\n"forkey,snippetinSNIPPETS.items():result+=f"- `{key}`:{snippet['name']}\n"returnresult@mcp.resource("snippets://library/{snippet_id}")defget_snippet(snippet_id:str)->str:"""获取指定的代码片段"""# snippet_id 格式如 "python/singleton"ifsnippet_idinSNIPPETS:snippet=SNIPPETS[snippet_id]return(f"#{snippet['name']}\n"f"```{snippet['language']}\n"f"{snippet['code']}\n"f"```")returnf"未找到代码片段:{snippet_id}"代码解读:
@mcp.resource("snippets://library")使用自定义 URI scheme 注册资源snippets://library/{snippet_id}是参数化 URI,{snippet_id}会被自动提取为函数参数- 资源返回的内容可以是纯文本或 Markdown,LLM 会根据内容格式进行理解
5.2 代码审查提示模板
# src/dev_assistant/prompts/code_review.py# 代码审查提示模板 —— 为 LLM 提供结构化的代码审查指引frommcp.server.fastmcpimportFastMCPdefregister_code_review_prompts(mcp:FastMCP):"""注册代码审查相关的提示模板"""@mcp.prompt()defcode_review(code:str,language:str="python",focus:str="general")->str:""" 生成代码审查提示。 Args: code: 待审查的代码 language: 编程语言 focus: 审查重点,可选 "general"(综合), "security"(安全), "performance"(性能) """focus_instructions={"general":"""综合审查以下方面: 1. 代码风格与可读性 2. 错误处理的完整性 3. 类型标注的准确性 4. 文档字符串的质量 5. 潜在的 Bug""","security":"""重点审查以下安全问题: 1. 输入验证与注入防护 2. 敏感数据处理 3. 权限控制 4. 依赖安全性 5. 错误信息泄露""","performance":"""重点审查以下性能问题: 1. 时间复杂度分析 2. 内存使用效率 3. I/O 操作优化 4. 并发安全性 5. 缓存策略"""}returnf"""你是一位资深{language}代码审查专家。请对以下代码进行专业审查。 ## 审查重点{focus_instructions.get(focus,focus_instructions["general"])}## 输出格式 请按以下格式输出审查结果: ### 评分 给出 1-10 分的综合评分 ### 问题列表 列出发现的问题,每个问题包含: - 🔴/🟡/🟢 严重程度 - 问题描述 - 修复建议(含代码示例) ### 优化建议 给出整体优化方向 ## 待审查代码 ```{language}{code}```"""六、完整 Server 入口
# src/dev_assistant/server.py# 开发助手 MCP Server 主入口frommcp.server.fastmcpimportFastMCPfrom.tools.formatterimportregister_formatter_toolsfrom.tools.json_validatorimportregister_json_toolsfrom.tools.regex_testerimportregister_regex_toolsfrom.resources.snippetsimportregister_snippet_resourcesfrom.prompts.code_reviewimportregister_code_review_promptsdefcreate_server()->FastMCP:"""创建并配置 MCP Server"""mcp=FastMCP(name="dev-assistant",instructions="""这是一个面向开发者的 MCP 工具集。 提供以下能力: - 代码格式化(Python PEP8/Black 风格) - JSON 校验(支持 Schema 验证) - 正则表达式测试 - 常用代码片段库 - 代码审查提示模板 请根据用户需求选择合适的工具。""")# 注册所有工具register_formatter_tools(mcp)register_json_tools(mcp)register_regex_tools(mcp)# 注册资源register_snippet_resources(mcp)# 注册提示模板register_code_review_prompts(mcp)returnmcpdefmain():"""主入口函数"""mcp=create_server()mcp.run(transport="stdio")if__name__=="__main__":main()七、测试与调试
7.1 MCP Inspector
MCP 官方提供了Inspector工具,可以可视化地测试 MCP Server:
# 使用 Inspector 测试 Servernpx @modelcontextprotocol/inspector python src/dev_assistant/server.pyInspector 提供了以下功能:
- 查看 Server 暴露的工具列表
- 手动调用工具并查看结果
- 查看资源内容
- 测试提示模板
- 查看原始 JSON-RPC 消息
7.2 单元测试
# tests/test_server.py# MCP Server 单元测试importpytestfromdev_assistant.serverimportcreate_server@pytest.fixturedefserver():"""创建测试用 Server 实例"""returncreate_server()classTestJSONValidator:"""JSON 校验工具测试"""deftest_valid_json(self,server):"""测试有效 JSON 的校验"""# 通过 FastMCP 的内部方法调用工具result=server.call_tool("validate_json",{"json_string":'{"name": "test", "value": 42}'})assert"✅"inresultdeftest_invalid_json(self,server):"""测试无效 JSON 的校验"""result=server.call_tool("validate_json",{"json_string":'{"name": "test", value: 42}'})assert"❌"inresultdeftest_json_with_schema(self,server):"""测试 JSON Schema 验证"""json_str='{"name": "test", "age": 25}'schema='{"type": "object", "properties": {"name": {"type": "string"}, "age": {"type": "integer"}}, "required": ["name"]}'result=server.call_tool("validate_json",{"json_string":json_str,"schema":schema})assert"✅"inresult7.3 Claude Desktop 集成测试
将 Server 接入 Claude Desktop 进行端到端测试:
// ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)// %APPDATA%\Claude\claude_desktop_config.json (Windows){"mcpServers":{"dev-assistant":{"command":"python","args":["-m","dev_assistant.server"],"env":{"PYTHONPATH":"/path/to/dev-assistant-mcp/src"}}}}配置完成后,在 Claude Desktop 中可以直接使用:
- “帮我格式化这段 Python 代码”
- “校验这个 JSON 是否正确”
- “给我一个 Python 单例模式的代码片段”
- “帮我审查这段代码的安全性”
八、开发最佳实践
8.1 工具设计原则
- 单一职责:每个工具只做一件事,保持简单明确
- 描述清晰:docstring 就是工具说明书,LLM 会根据它决定何时使用
- 错误友好:返回有意义的错误信息,而非抛出异常
- 参数验证:在工具内部验证参数,而非依赖外部
8.2 安全注意事项
- 永远不要信任工具描述:工具的
annotations(如readOnlyHint)应被视为不可信 - 限制执行范围:使用沙箱、白名单等机制限制工具的执行权限
- 审计日志:记录所有工具调用,便于事后审查
- 输入消毒:对外部输入进行严格的验证和消毒
8.3 性能优化
- 懒加载:只在需要时加载重型依赖
- 缓存:对频繁访问的资源进行缓存
- 异步操作:使用
async/await处理 I/O 密集型操作 - 超时控制:为所有外部调用设置合理的超时
九、总结
构建一个 MCP Server 并不复杂,但需要注意以下几个关键点:
- FastMCP 大幅降低了开发门槛:装饰器驱动的设计让开发者可以专注于业务逻辑
- 工具描述是核心:LLM 通过工具描述来理解何时、如何使用工具
- 三大原语各司其职:Tools 用于执行操作,Resources 用于提供数据,Prompts 用于引导 LLM
- 测试是必须的:使用 MCP Inspector 进行手动测试,使用单元测试覆盖核心逻辑
在下一篇文章中,我们将从 Client 端出发,探讨如何在 Agent 中集成和调用 MCP Server。
参考资料
- Anthropic. “MCP Server Development Guide.”modelcontextprotocol.io, https://modelcontextprotocol.io/quickstart/server
- MCP Python SDK.github.com, https://github.com/modelcontextprotocol/python-sdk
- Anthropic. “MCP Server Features — Tools.”modelcontextprotocol.io, https://modelcontextprotocol.io/specification/2025-11-25/server/tools
- Anthropic. “MCP Server Features — Resources.”modelcontextprotocol.io, https://modelcontextprotocol.io/specification/2025-11-25/server/resources
- MCP Inspector.github.com, https://github.com/modelcontextprotocol/inspector
本系列覆盖AI 大模型基础、Agent 开发、MCP 协议、Skill 开发、RAG、模型微调、部署推理七大方向,从入门到实战的全栈内容持续更新中。
所有文章的 Markdown 源文件、可运行代码、高清配图已整理成完整资料包。
👍 点赞 + ⭐ 关注,评论区扣「1」,挨个发你领取方式 👇