| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- # my_mcp_server.py —— 一个极简的自定义 MCP 服务
- from mcp.server.fastmcp import FastMCP
- from datetime import datetime
- from urllib.parse import unquote
- # ============================================================
- # 第一步:创建 FastMCP 实例,相当于初始化一个 Server 框架
- # ============================================================
- mcp = FastMCP(name="my-tools")
- # ============================================================
- # 第二步:用 @mcp.tool() 装饰器注册工具
- # 装饰器会自动提取函数的 type hints 和 docstring 作为工具描述
- # ============================================================
- @mcp.tool()
- def get_current_time() -> str:
- """
- 获取当前日期和时间,返回格式友好的字符串。
- 适用场景:当用户问"现在几点"或"今天几号"时调用。
- """
- now = datetime.now()
- return f"现在是 {now.year}年{now.month}月{now.day}日,{now.strftime('%H:%M:%S')}"
- @mcp.tool()
- def calculate_bmi(weight_kg: float, height_cm: float) -> str:
- """
- 根据体重(公斤)和身高(厘米)计算 BMI 指数。
- 参数:
- - weight_kg: 体重,单位公斤
- - height_cm: 身高,单位厘米
- 返回:BMI 数值 + 健康评级
- """
- height_m = height_cm / 100
- bmi = weight_kg / (height_m ** 2)
- # 按中国标准分级
- if bmi < 18.5:
- level = "偏瘦,多吃点"
- elif bmi < 24:
- level = "正常,继续保持"
- elif bmi < 28:
- level = "偏胖,注意饮食"
- else:
- level = "该运动了兄弟"
- return f"BMI = {bmi:.1f},{level}"
- # ============================================================
- # 第三步:用 @mcp.resource() 注册静态资源
- # 资源是"模板化"的数据端点,适合暴露文章、配置、文件内容等
- # URI 中用 {变量名} 定义路径参数
- # ============================================================
- # 模拟一个简易知识库
- KNOWLEDGE_BASE = {
- "请假流程": "OA 系统提交 → 直属领导审批 → HR 备案。年假需提前 3 天申请。",
- "报销标准": "市内交通实报实销(上限 100/天),住宿标准 350/晚(一线城市 450/晚)。",
- "入职材料": "身份证原件 + 复印件、学历学位证、体检报告、离职证明、银行卡。",
- }
- @mcp.resource("knowledge://{topic}")
- def query_knowledge(topic: str) -> str:
- """
- 查询公司内部知识库,返回指定主题的说明文档。
- 调用方式(Client 端):session.read_resource("knowledge://报销标准")
- """
- # MCP 协议中 URI 的非 ASCII 字符会被 Pydantic AnyUrl 自动
- # URL 编码(如 "请假流程" → "%E8%AF%B7%E5%81%87%E6%B5%81%E7%A8%8B"),
- # 但 FastMCP 的 ResourceTemplate.matches() 提取参数时不会自动解码,
- # 所以这里需要手动 unquote。
- topic = unquote(topic)
- print(f"查询知识库:{topic}")
- result = KNOWLEDGE_BASE.get(topic, f"没找到关于「{topic}」的记录,请联系 HR 更新知识库。")
- return result
- # ============================================================
- # 第四步:启动 Server
- # ============================================================
- if __name__ == "__main__":
- # SSE 模式:作为独立 HTTP 服务运行,适合远程调用和调试
- mcp.settings.host = "0.0.0.0"
- mcp.settings.port = 8000
- mcp.run(transport="sse")
|