用 Python 手写一个 MCP 服务端:把本地运维脚本接进 AI Agent
最近把几个平时手动跑的运维小脚本接进了 AI Agent,用的是 MCP(Model Context Protocol)。整个过程比想象中简单:不需要改脚本逻辑,只要在外面包一层协议适配,Agent 就能像调用内置工具一样调用它们。这里记录一下完整实现和踩到的坑。
## 一、MCP 解决的是什么问题
在没有 MCP 之前,给 Agent 接工具基本是三种做法:写死在提示词里让模型输出命令、自己定一套 HTTP 接口、或者直接把脚本内容塞进上下文。前两种要求每换一个模型就重写一遍胶水层,第三种则会迅速把上下文撑爆。MCP 的价值在于把“工具的描述与调用”抽成标准协议:服务端声明工具的名称、参数 schema 和行为说明,客户端负责把这些声明翻译成模型能理解的函数调用格式。换模型、换 Agent 框架,服务端一行都不用改。
## 二、服务端骨架:stdio 传输 + 工具声明
最小可用的服务端只需要实现三个能力:初始化握手、列出工具、执行工具。传输层用 stdio 最省事,Agent 拉起子进程,通过标准输入输出交换 JSON-RPC 消息,不占端口、不需要鉴权。工具声明里最重要的是 inputSchema,用 JSON Schema 描述参数,模型据此生成调用参数;description 则决定模型会不会在正确的时机选择这个工具,写得含糊是常见的失败原因。
## 三、把已有脚本包成工具
我沿用的原则是“一个脚本一个工具,参数扁平化”。比如磁盘巡检脚本原本接受一堆位置参数,包成工具后改成 host、threshold、dry_run 三个具名参数,并且把 dry_run 默认设为 true。这样模型第一次调用时只会做只读检查,确认无误后再显式传 false 执行真实操作。执行层用 subprocess 调用脚本,捕获 stdout 与退出码,把结果整理成结构化文本返回,避免把几百行原始日志直接丢回上下文。
## 四、接入 Agent 与联调
在 Agent 侧配置好服务端启动命令后,先跑一次工具列表,确认 schema 被正确解析;再用一句自然语言触发调用,观察模型是否选对了工具、参数是否符合 schema。联调阶段我习惯打开服务端的请求日志,把每次 tools/call 的入参打印出来,这样能快速区分是“模型没选对工具”还是“参数填错了”。对于有副作用的工具,超时和幂等要提前设计好,否则重试一次就可能重复执行。
## 五、几个容易踩的坑
第一,stdio 模式下绝对不能在 stdout 打印调试信息,任何非协议输出都会破坏消息流,调试日志一律走 stderr。第二,工具返回内容要控制长度,超过几千字符就该截断或落盘只返回摘要。第三,错误要区分“可重试”和“不可重试”,把错误类型写进返回体,让模型自己决定是否换个参数再试。第四,别让一个工具承担太多职责,工具粒度粗了,模型选错的概率会明显上升。
整体下来,一个服务端不到两百行代码,就能把这几年攒下的脚本资产盘活。如果你的 Agent 也需要操作真实环境,MCP 是目前成本最低的一条路。
- 点赞
- 收藏
- 关注作者
评论(0)