02-快速构建MCP服务器
本文介绍了如何使用FastMCP框架快速构建MCP服务器。FastMCP是一个Python框架,通过装饰器语法(@mcp.tool()、@mcp.resource()、@mcp.prompt())简化组件定义,支持自动类型推断和多传输协议。文章详细展示了构建数学计算服务器和BMI计算服务器的完整流程,包括定义提示模板(系统提示、问题提示、计算指导)、资源(数学常量、动态问候、配置信息)和工具(基础
02-快速构建MCP服务器
概述
在上一篇《MCP协议入门指南》中,我们介绍了 MCP 协议的基本概念和核心组件。本文将详细介绍如何使用 FastMCP 框架快速构建完整的 MCP 服务器,包括数学计算服务器和 BMI 计算服务器,并展示如何定义工具、资源和提示模板。
FastMCP框架简介
FastMCP 是一个用于快速构建 MCP 服务器的 Python 框架,它提供了简洁的 API 和强大的功能。
核心特性
- 装饰器语法: 使用
@mcp.tool(),@mcp.resource(),@mcp.prompt()快速定义组件 - 自动类型推断: 自动生成 JSON Schema
- 多传输支持: 同时支持 stdio 和 HTTP 传输
- 开发友好: 内置开发工具和调试功能
安装
# 使用 uv
uv add fastmcp
# 或使用 pip
pip install fastmcp
项目准备
项目结构
mcp_demo/
├── math_mcp_server_stdio.py # 数学计算服务器(Stdio模式)
├── math_mcp_server_http.py # 数学计算服务器(HTTP模式)
├── bmi_mcp_server.py # BMI计算服务器
└── pyproject.toml # 项目配置
依赖配置
pyproject.toml 配置:
[project]
name = "mcp-demo"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"fastmcp>=2.14.3",
"mcp>=0.9.0",
]
构建数学计算 MCP 服务器
基础结构
首先创建数学计算服务器的基础结构:
from mcp.server.fastmcp import FastMCP
import math
# 创建 MCP 服务器实例
mcp = FastMCP("Math")
# 服务器版本信息
SERVER_VERSION = "1.0.0"
定义提示模板
提示模板用于定义 AI 助手的行为模式。
1. 系统提示模板
@mcp.prompt()
def system_prompt() -> str:
"""
系统提示模板
定义AI助手的基本行为和角色
"""
return """
You are an AI assistant specialized in mathematical calculations.
- Use the available tools when needed to perform calculations
- Always explain your reasoning before calling a tool
- Show step-by-step solutions
- Provide clear and concise answers
- If a calculation is needed, use the appropriate tool
"""
2. 数学问题提示模板
@mcp.prompt()
def example_prompt(question: str) -> str:
"""
数学问题提示模板
用于引导AI助手回答数学问题
"""
return f"""
You are a math assistant. Answer the question step by step.
Question: {question}
Show your work and explain each step clearly.
"""
3. 计算指导模板
@mcp.prompt()
def calculation_guide(operation: str) -> str:
"""
计算指导模板
提供特定运算类型的指导
"""
guides = {
"addition": "To add two numbers, combine their values.",
"multiplication": "To multiply, add one number to itself the number of times specified by the other.",
"division": "To divide, split one number into equal parts of another.",
"subtraction": "To subtract, find the difference between two numbers."
}
return f"""
Calculation Guide for {operation}:
{guides.get(operation.lower(), "General calculation method")}
Always use the appropriate tool for accurate results.
"""
定义资源
资源提供静态或动态的数据访问能力。
1. 数学常量资源
@mcp.resource("constant://pi")
def get_pi() -> str:
"""
圆周率常数
返回数学常数π(Pi)的高精度值
"""
return f"{math.pi}"
@mcp.resource("constant://e")
def get_euler_number() -> str:
"""
自然常数
返回自然对数的底数e(欧拉数)的高精度值
"""
return f"{math.e}"
@mcp.resource("constant://golden_ratio")
def get_golden_ratio() -> str:
"""
黄金比例
返回黄金比例φ的值(约等于1.618...)
"""
return f"{(1 + math.sqrt(5)) / 2}"
2. 动态资源
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""
个性化问候
根据提供的名字返回问候语
"""
return f"Hello, {name}! Welcome to the Math MCP Server."
3. 配置资源
@mcp.resource("config://app")
def get_config() -> str:
"""
应用配置
返回服务器配置信息(JSON格式)
"""
import json
config = {
"server_name": "Math MCP Server",
"version": "1.0.0",
"features": ["basic_arithmetic", "constants", "prompts"],
"supported_operations": ["add", "subtract", "multiply", "divide", "power", "sqrt", "factorial"],
"transport": "stdio"
}
return json.dumps(config, indent=2, ensure_ascii=False)
4. 服务器能力资源
@mcp.resource("info://capabilities")
def get_capabilities() -> str:
"""
服务器能力信息
详细说明服务器提供的功能
"""
capabilities = """
Math MCP Server Capabilities:
Tools:
- add(a, b): Addition of two numbers
- subtract(a, b): Subtraction of two numbers
- multiply(a, b): Multiplication of two numbers
- divide(a, b): Division of two numbers
- power(base, exponent): Exponentiation
- sqrt(number): Square root
- factorial(n): Factorial
Resources:
- constant://pi: Pi constant (3.14159...)
- constant://e: Euler's number (2.71828...)
- constant://golden_ratio: Golden ratio (1.61803...)
- greeting://{name}: Personalized greeting
- config://app: Application configuration
- info://capabilities: This capability list
Prompts:
- example_prompt(question): Math question template
- system_prompt(): System behavior template
- calculation_guide(operation): Operation guide
"""
return capabilities
定义工具
工具是可执行的函数,供 AI 助手调用以完成特定任务。
1. 基础运算工具
@mcp.tool()
def add(a: int, b: int) -> str:
"""
加法运算
计算两个整数的和
Args:
a: 第一个加数
b: 第二个加数
Returns:
计算结果和过程的描述字符串
"""
result = a + b
return f"{a} + {b} = {result}"
@mcp.tool()
def subtract(a: int, b: int) -> str:
"""
减法运算
计算两个整数的差
Args:
a: 被减数
b: 减数
Returns:
计算结果和过程的描述字符串
"""
result = a - b
return f"{a} - {b} = {result}"
@mcp.tool()
def multiply(a: int, b: int) -> str:
"""
乘法运算
计算两个整数的乘积
Args:
a: 第一个乘数
b: 第二个乘数
Returns:
计算结果和过程的描述字符串
"""
result = a * b
return f"{a} * {b} = {result}"
@mcp.tool()
def divide(a: int, b: int) -> str:
"""
除法运算
计算两个整数的商(浮点数结果)
Args:
a: 被除数
b: 除数(不能为零)
Returns:
计算结果和过程的描述字符串
Raises:
ValueError: 当除数为零时
"""
if b == 0:
raise ValueError("除数不能为零 (Divisor cannot be zero)")
result = a / b
return f"{a} / {b} = {result}"
2. 高级运算工具
@mcp.tool()
def power(base: int, exponent: int) -> str:
"""
幂运算
计算基数的整数次幂
Args:
base: 底数
exponent: 指数(必须为非负整数)
Returns:
计算结果和过程的描述字符串
Raises:
ValueError: 当指数为负数时
"""
if exponent < 0:
raise ValueError("指数必须为非负整数 (Exponent must be non-negative)")
result = base ** exponent
return f"{base}^{exponent} = {result}"
@mcp.tool()
def sqrt(number: int) -> str:
"""
平方根运算
计算一个非负整数的平方根
Args:
number: 要计算平方根的非负整数
Returns:
计算结果和过程的描述字符串
Raises:
ValueError: 当数为负数时
"""
if number < 0:
raise ValueError("不能计算负数的平方根 (Cannot calculate square root of negative number)")
result = math.sqrt(number)
if result.is_integer():
return f"√{number} = {int(result)}"
else:
return f"√{number} ≈ {result:.6f}"
@mcp.tool()
def factorial(n: int) -> str:
"""
阶乘运算
计算一个非负整数的阶乘
Args:
n: 非负整数
Returns:
计算结果和过程的描述字符串
Raises:
ValueError: 当n为负数时
"""
if n < 0:
raise ValueError("阶乘只能计算非负整数 (Factorial only defined for non-negative integers)")
result = math.factorial(n)
return f"{n}! = {result}"
服务器入口
if __name__ == "__main__":
print("=" * 60)
print("Math MCP Server (Stdio Mode)")
print("=" * 60)
print("")
print("Server Information:")
print(" - Name: Math")
print(f" - Version: {SERVER_VERSION}")
print(" - Transport: Stdio")
print("")
print("Available Tools (7):")
print(" 1. add(a: int, b: int) -> str")
print(" 加法运算 (Addition)")
print(" 2. subtract(a: int, b: int) -> str")
print(" 减法运算 (Subtraction)")
print(" 3. multiply(a: int, b: int) -> str")
print(" 乘法运算 (Multiplication)")
print(" 4. divide(a: int, b: int) -> str")
print(" 除法运算 (Division)")
print(" 5. power(base: int, exponent: int) -> str")
print(" 幂运算 (Power)")
print(" 6. sqrt(number: int) -> str")
print(" 平方根运算 (Square Root)")
print(" 7. factorial(n: int) -> str")
print(" 阶乘运算 (Factorial)")
print("")
print("Available Resources (6):")
print(" 1. constant://pi")
print(" 圆周率常数 (Pi constant)")
print(" 2. constant://e")
print(" 自然常数 (Euler's number)")
print(" 3. constant://golden_ratio")
print(" 黄金比例 (Golden ratio)")
print(" 4. greeting://{name}")
print(" 个性化问候 (Personalized greeting)")
print(" 5. config://app")
print(" 应用配置 (App configuration)")
print(" 6. info://capabilities")
print(" 服务器能力 (Server capabilities)")
print("")
print("Available Prompts (3):")
print(" 1. example_prompt(question: str) -> str")
print(" 数学问题模板")
print(" 2. system_prompt() -> str")
print(" 系统提示模板")
print(" 3. calculation_guide(operation: str) -> str")
print(" 计算指导模板")
print("")
print("Server is ready and waiting for connections...")
print("Note: This server runs in stdio mode.")
print("Use the HTTP version (math_mcp_server_http.py) for HTTP mode.")
print("=" * 60)
print("")
mcp.run() # Run server via stdio
构建 HTTP 模式服务器
HTTP 模式服务器与 stdio 模式的主要区别在于传输方式的配置。
关键差异
if __name__ == "__main__":
print("=" * 60)
print("Math MCP Server (HTTP Mode)")
print("=" * 60)
print("")
print("Server Information:")
print(" - Name: Math")
print(f" - Version: {SERVER_VERSION}")
print(" - Transport: HTTP (streamable-http)")
print(" - URL: http://0.0.0.0:8000/mcp")
print("")
# ... 工具和资源列表 ...
print("Starting HTTP server...")
print("Waiting for client connections...")
print("Note: This server runs in HTTP mode.")
print("Use the stdio version (math_mcp_server_stdio.py) for stdio mode.")
print("=" * 60)
print("")
mcp.run(transport="streamable-http") # Run server via streamable-http
启动 HTTP 服务器
python math_mcp_server_http.py
服务器将在 http://0.0.0.0:8000/mcp 上监听连接。
构建 BMI 计算服务器
BMI 计算服务器是一个更简单的示例,展示了如何构建专注于特定功能的 MCP 服务器。
完整代码
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("BMI")
@mcp.tool()
def calculate_bmi(weight: int, height: int) -> str:
"""Calculate BMI
Args:
weight: Weight in kilograms (kg)
height: Height in meters (m)
Returns:
BMI value and interpretation
"""
bmi = weight / (height * height)
# BMI 分类
if bmi < 18.5:
category = "Underweight (偏瘦)"
elif 18.5 <= bmi < 25:
category = "Normal weight (正常)"
elif 25 <= bmi < 30:
category = "Overweight (超重)"
else:
category = "Obese (肥胖)"
return f"BMI: {bmi:.2f}\n分类: {category}"
if __name__ == "__main__":
print("=" * 60)
print("BMI MCP Server")
print("=" * 60)
print("")
print("Server Information:")
print(" - Name: BMI")
print(" - Transport: HTTP (streamable-http)")
print(" - URL: http://localhost:8000/mcp")
print(" - Available Tools:")
print(" + calculate_bmi(weight: int, height: int) -> str")
print(" Calculate Body Mass Index")
print(" weight: Weight in kilograms (kg)")
print(" height: Height in meters (m)")
print("")
print("Starting HTTP server...")
print("Waiting for client connections...")
print("=" * 60)
print("")
mcp.run(transport="streamable-http")
启动 BMI 服务器
python bmi_mcp_server.py
测试服务器
使用 Stdio 客户端测试
创建测试客户端 test_math_server.py:
import asyncio
from mcp.client.stdio import stdio_client
from mcp import ClientSession, StdioServerParameters
async def main():
server_params = StdioServerParameters(
command="python",
args=["math_mcp_server_stdio.py"]
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 测试工具调用
print("测试工具调用:")
result = await session.call_tool("add", {"a": 10, "b": 20})
print(f" add(10, 20) = {result.content[0].text}")
result = await session.call_tool("multiply", {"a": 5, "b": 6})
print(f" multiply(5, 6) = {result.content[0].text}")
# 测试资源读取
print("\n测试资源读取:")
resource = await session.read_resource("constant://pi")
print(f" Pi = {resource.contents[0].text}")
resource = await session.read_resource("greeting://Alice")
print(f" Greeting = {resource.contents[0].text}")
# 测试提示模板
print("\n测试提示模板:")
prompt = await session.get_prompt("example_prompt", {"question": "What is 1+1?"})
print(f" Prompt = {prompt.messages[0].content.text}")
if __name__ == "__main__":
asyncio.run(main())
运行测试:
python test_math_server.py
使用 HTTP 客户端测试
创建测试客户端 test_bmi_server.py:
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def main():
server_url = "http://localhost:8000/mcp"
async with streamablehttp_client(server_url) as (read, write, _):
async with ClientSession(read, write) as session:
await session.initialize()
# 测试 BMI 计算
result = await session.call_tool("calculate_bmi", {
"weight": 70,
"height": 1.75
})
print(f"BMI 计算结果:\n{result.content[0].text}")
if __name__ == "__main__":
asyncio.run(main())
运行测试:
# 终端1: 启动 BMI 服务器
python bmi_mcp_server.py
# 终端2: 运行测试
python test_bmi_server.py
最佳实践
1. 工具设计原则
- 单一职责: 每个工具只做一件事
- 明确的参数: 使用类型注解和文档字符串
- 错误处理: 提供清晰的错误信息
- 返回格式: 保持一致的返回格式
2. 资源命名规范
- 使用 URI 格式:
scheme://path/{param} - 保持层次清晰:
config://app,data://users/{id} - 参数使用蛇形命名:
greeting://{user_name}
3. 提示模板设计
- 明确角色定义
- 提供使用指导
- 包含示例说明
- 保持简洁明了
4. 服务器配置
# 良好的服务器配置示例
if __name__ == "__main__":
# 显示服务器信息
print_banner()
# 选择传输方式
transport = os.getenv("TRANSPORT", "stdio")
if transport == "http":
# HTTP 配置
host = os.getenv("HOST", "0.0.0.0")
port = int(os.getenv("PORT", "8000"))
mcp.run(transport="streamable-http", host=host, port=port)
else:
# Stdio 配置
mcp.run(transport="stdio")
故障排查
问题 1: 服务器启动失败
错误信息:
ModuleNotFoundError: No module named 'fastmcp'
解决方案:
uv sync
# 或
pip install fastmcp
问题 2: 工具调用参数错误
错误信息:
ValidationError: type=integer_type_constrained
解决方案:
- 检查参数类型是否匹配
- 验证参数值在有效范围内
- 使用 JSON Schema 验证工具定义
问题 3: HTTP 端口被占用
错误信息:
OSError: [Errno 48] Address already in use
解决方案:
# 查找占用端口的进程
lsof -i :8000
# 终止进程
kill -9 <PID>
阅读顺序建议
- 01-MCP协议入门指南: 了解 MCP 基本概念和核心组件
- 02-快速构建MCP服务器: 使用 FastMCP 构建服务器
- 03-MCP客户端开发实战: 开发 stdio 和 HTTP 客户端
- 04-LLM与MCP集成实践: 集成到 LangGraph 构建智能代理
- 05-多服务器架构与最佳实践: 多服务器架构和生产部署
总结
本文详细介绍了如何使用 FastMCP 框架构建 MCP 服务器,包括:
- 数学计算服务器的完整实现(7个工具、6个资源、3个提示模板)
- BMI 计算服务器的简化实现
- stdio 和 HTTP 两种传输方式的配置
- 服务器测试和故障排查
在下一篇《MCP客户端开发实战》中,我们将学习如何开发 MCP 客户端,包括 stdio 和 HTTP 两种传输方式的客户端实现,以及如何调用工具、读取资源和获取提示模板。
参考资源
文章标签
FastMCP, MCP服务器, Python开发, 工具调用, 资源管理, 提示模板, HTTP服务器, stdio传输, 开发实战
更多推荐


所有评论(0)