侧边栏壁纸
博主头像
毕业帮 博主等级

提供丰富的资源和服务,涵盖从论文写作、毕业设计、职业规划、就业准备等多个方面

  • 累计撰写 66 篇文章
  • 累计创建 18 个标签
  • 累计收到 3 条评论

目 录CONTENT

文章目录

Part 6:MCP协议与Skills系统详解 - 工具化AI应用的基石

流苏
2026-03-03 / 0 评论 / 0 点赞 / 1 阅读 / 0 字 / 正在检测是否收录...
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Part 6:MCP协议与Skills系统详解 - 工具化AI应用的基石

学习目标:理解MCP(Model Context Protocol)如何实现LLM与外部系统解耦,掌握Skills系统设计与开发方法,能构建工具化、可扩展的AI应用


一、为什么要MCP?—— 工具碎片化的痛点

1.1 问题:每个框架都有自己的工具定义方式

现实困境

  • LangChain有Tool定义格式
  • LlamaIndex有Tool定义格式
  • OpenAI有Function Calling格式
  • 每个平台(Coze/Dify)都有自己的插件系统

痛点

  • ❌ 为一个平台开发的工具,不能在其他平台复用
  • ❌ 企业开发内部工具,要适配多个AI应用 → 重复劳动
  • ❌ 工具提供方(如天气API)要对接N个AI框架 → 维护成本爆炸

1.2 MCP的愿景:统一标准

类比:USB接口

  • 电脑(AI应用)只需要一个USB口
  • U盘、键盘、鼠标(各种工具)都通过USB连接
  • USB芯片厂商(工具开发方)不用关心电脑品牌

MCP的目标

  • ✅ 工具定义一次, everywhere可用
  • ✅ AI应用只需对接MCP标准,不关心工具实现细节
  • ✅ 工具在独立沙箱运行,安全可控

二、MCP核心概念:三要素

2.1 架构总览

┌─────────────┐        JSON-RPC over STDIO        ┌─────────────┐
│   Client    │◄────────────────────────────────►│   Server    │
│ (AI App)    │   (Client-Server消息协议)        │  (Tool)     │
└─────────────┘                                  └─────────────�
       │                                                   │
   LLM交互                                             执行业务逻辑
   (调用工具)                                            (访问DB/API)

角色

  • Client:AI应用(如Claude Code、OpenCode)
  • Server:工具提供方(文件操作、数据库查询、自定义业务)
  • Protocol:JSON-RPC 2.0 over STDIO(本地)或 SSE(远程)

2.2 Resources(资源):只读数据源

定义:文件、数据库记录、API响应的只读访问。

特点

  • 只读(不能写)
  • 可以有URI标识(如 file:///path/to/doc.txt
  • 可列出(list)和读取(read)

例子

资源类型:
- 文件:file:///home/user/readme.md
- 数据库行:postgres://table/users/id=123
- API响应:http://api.company.com/employees?dept=sales

场景

  • AI问:"用户123的个人信息?"
  • Client向MCP Server请求资源 user://123
  • Server返回JSON数据
  • AI基于数据回答

2.3 Tools(工具):可执行操作

定义:能改变状态或执行计算的函数。

与Resources区别

  • Resources:只读(查)
  • Tools:可写(增删改查 + 执行动作)

Tool定义结构

{
  "name": "create_ticket",
  "description": "创建客服工单",
  "inputSchema": {
    "type": "object",
    "properties": {
      "user_id": {"type": "string", "description": "用户ID"},
      "issue": {"type": "string", "description": "问题描述"},
      "priority": {"type": "string", "enum": ["low", "medium", "high"]}
    },
    "required": ["user_id", "issue"]
  }
}

Client调用流程

1. Client获取Server支持的Tool列表
2. LLM决定调用哪个Tool,生成参数
3. Client发送 "tools/call" JSON-RPC消息
4. Server执行,返回结果
5. Client把结果喂给LLM,继续对话

2.4 Prompts:可复用的Prompt模板

定义:预定义的Prompt片段,带参数,可被LLM调用。

场景

Developer写好了常用Prompt:
- "review_code":审查代码,参数(file_path, language)
- "explain_error":解释错误信息,参数(error_log)

AI在对话中:
用户:"帮我看看这段Python代码有没有bug"
AI:→ (自动触发)调用Prompt "review_code" + 代码作为参数
    → 返回审查结果

价值

  • 非技术用户写的Prompt,技术用户复用
  • 标准化输出格式
  • Prompt版本管理

三、Skills系统:MCP的应用实践

3.1 什么是Skill?

Skill = 一组Tools + Resources + Prompts + 权限定义

类比

  • MCP是"USB接口标准"
  • Skill是"插在USB口的实际设备"(U盘、键盘)

Skill定义文件(SKILL.md或YAML)

name: file-operator
description: 文件读写操作工具集
version: 1.0.0
permissions:
  - file_read
  - file_write
tools:
  - name: read_file
    description: 读取文件内容
    inputSchema:
      type: object
      properties:
        filePath: {type: string, description: 文件路径}
      required: [filePath]
  - name: write_file
    description: 写入文件(覆盖)
    inputSchema: ...
    permissions: [file_write]
resources:
  - name: local_files
    uri: file:///**
    description: 本地文件系统(只读列举)

3.2 权限模型与安全沙箱

声明式权限

Skill运行前声明:
我需要:file_read、file_write、network_access
用户确认:Yes/No

沙箱隔离

  • 限制文件访问范围:只能访问 /workspace/ 目录
  • 禁止危险操作:删系统文件、fork炸弹、无限循环
  • 资源限制:CPU时间、内存、网络带宽

审计日志

时间戳 | 用户 | 工具调用 | 参数 | 结果 | 耗时
────────┼──────┼──────────┼──────┼──────┼──────
10:23:01| Alice| write_file|path=...|成功| 50ms

便于追溯和合规。


四、工具定义规范最佳实践

4.1 参数类型系统

支持类型(JSON Schema子集):

  • string:文本
  • number:数字
  • boolean:布尔
  • array:数组(如文件路径列表)
  • object:对象(支持嵌套)

必需 vs 可选

{
  "required": ["filePath", "content"],  ← 必须提供的参数
  "properties": {
    "filePath": {"type": "string"},
    "content": {"type": "string"},
    "encoding": {"type": "string", "default": "utf-8"}  ← 可选,有默认值
  }
}

4.2 描述的最佳实践

坏例子

"description": "打开文件"

问题:不知道是读还是写?会不会覆盖?

好例子

"description": "读取文件内容,返回字符串。如果文件不存在,抛出错误。注意:文件编码必须为UTF-8。"
  • ✅ 明确操作(读)
  • ✅ 明确副作用(无副作用,只读)
  • ✅ 明确错误处理(抛异常)
  • ✅ 给出约束(UTF-8)

给LLM看的描述要具体

"description": "搜索Git commit历史。参数:author(作者邮箱)、since(起始日期,格式YYYY-MM-DD)、until(结束日期)。返回:最近10次提交的hash和message。"

LLM看到这个,就知道什么时候该用、怎么填参数。

4.3 设计模式

原子工具:单一功能,无副作用的工具

  • read_file:只读
  • write_file:只写
  • delete_file:只删

复合工具:封装多个原子操作为"高级功能"

  • refactor_code:内部调用 read→修改→write
  • deploy_service:build→push→kubectl apply

工具链:顺序调用完成复杂任务

"deploy_fullstack_app" = 
  [build_frontend, build_backend, push_docker, 
   update_kubernetes, notify_slack]

选择原则

  • 权限隔离严格的场景 → 原子工具(细粒度控制)
  • 业务流程固定 → 复合工具(简化调用)
  • 需要灵活编排 → 工具链(可配置顺序)

五、MCP服务器开发实战

5.1 用Python实现一个文件操作Server

目标:实现一个MCP Server,支持:

  • read_file
  • write_file
  • list_directory

Step 1:定义工具

tools = [
    {
        "name": "read_file",
        "description": "读取文件内容",
        "inputSchema": {
            "type": "object",
            "properties": {
                "path": {"type": "string", "description": "文件路径(相对于workspace)"}
            },
            "required": ["path"]
        }
    },
    # ... 其他工具
]

Step 2:实现回调函数

def read_file_callback(path: str) -> str:
    """读取文件,返回内容"""
    full_path = os.path.join(WORKSPACE, path)
    if not os.path.exists(full_path):
        raise FileNotFoundError(f"文件不存在: {path}")
  
    with open(full_path, 'r', encoding='utf-8') as f:
        return f.read()

Step 3:启动服务器(STDIO模式)

#!/usr/bin/env python3
import sys, json

def main():
    # 1. 读取Client消息(stdin)
    for line in sys.stdin:
        request = json.loads(line)
      
        # 2. 根据方法路由
        if request["method"] == "tools/list":
            response = {"tools": tools}
        elif request["method"] == "tools/call":
            tool_name = request["params"]["name"]
            args = request["params"]["arguments"]
          
            if tool_name == "read_file":
                result = read_file_callback(**args)
                response = {"content": result}
            # ... 其他工具
      
        # 3. 写回响应(stdout)
        print(json.dumps(response))
        sys.stdout.flush()

if __name__ == "__main__":
    main()

Step 4:处理错误

try:
    result = tool_callback(**args)
    response = {"content": [{"type": "text", "text": result}]}
except Exception as e:
    response = {
        "content": [{"type": "text", "text": f"错误: {str(e)}"}],
        "isError": True
    }

Step 5:测试

# 用mcp-cli工具手动测试
echo '{"method":"tools/call","params":{"name":"read_file","arguments":{"path":"test.txt"}}}' | python my_server.py

六、实际开发案例

案例1:文件操作Skill(OpenCode同款)

场景:在Claude Code / OpenCode中让AI读写本地文件。

工具列表

  • read_file(filePath):读文件
  • write_file(filePath, content):写文件(覆盖)
  • list_directory(path):列目录
  • search_files(pattern):正则搜索文件

权限设计

permissions:
  - file_read
  - file_write
  - file_delete  # 高危,需要双重确认

安全措施

  • 只能访问 workspace/ 目录(chroot-like)
  • ../ 路径穿越检测
  • 删除操作:先软删(.trash),7天后真删

调试技巧

  • 在Claude Code中调用:/read_file path/to/file.py
  • 看输出:文件内容是否正常?
  • 查看Server日志:工具执行是否成功?

案例2:企业CRM查询工具

场景:AI客服需要查询客户信息、订单历史。

工具定义

{
  "name": "query_customer",
  "description": "查询CRM系统中的客户信息",
  "inputSchema": {
    "type": "object",
    "properties": {
      "customer_id": {"type": "string"},
      "fields": {"type": "array", "items": {"type": "string"}}  // 指定返回字段
    },
    "required": ["customer_id"]
  }
}

实现

def query_customer(customer_id: str, fields: list = None) -> dict:
    # 1. 验证权限(当前用户是否有权查这个客户?)
    # 2. 连接CRM数据库(SQL)
    # 3. 只返回allowed fields(隐私字段屏蔽)
    # 4. 记录审计日志
    return {"name": "张三", "order_count": 5, "vip_level": "gold"}

隐私保护

  • 敏感字段(手机号、身份证)默认不返回
  • 需额外权限 view_pii 才能查
  • 每次查询记录日志,可追溯

七、实践任务

任务1:用Python实现"文件操作"MCP Server

要求

  • 支持3个工具:read_filewrite_filelist_directory
  • 工作目录限制在 ./workspace/(防止路径穿越)
  • 错误处理:文件不存在 → 友好提示
  • 日志:记录每次工具调用的参数和结果

测试

echo '{"method":"tools/list"}' | python server.py
echo '{"method":"tools/call","params":{"name":"read_file","arguments":{"path":"test.txt"}}}' | python server.py

任务2:为"项目进度查询"设计Tool Schema

场景:项目经理问"项目A进度如何?"

工具query_project_status(project_id, include_tasks, include_milestones)

任务输出

  1. 完整的JSON Schema(含描述、类型、required)
  2. 参数说明:
    • project_id:项目唯一标识
    • include_tasks:是否返回任务列表(布尔,默认False)
    • include_milestones:是否返回里程碑(布尔,默认False)
  3. 描述写清楚:"查询JIRA系统中的项目进度,返回当前状态、完成率、风险等级。如果include_tasks=True,额外返回最近10个任务的状态。"

任务3:在OpenCode中注册自定义Skill并测试

步骤

  1. 将任务1的Server放到OpenCode技能目录(~/.opencode/skills/
  2. 确保SKILL.md定义完整
  3. 重启OpenCode
  4. 在对话中测试:"读取当前目录的README.md文件"
  5. 截图并记录:Server日志、OpenCode输出是否正常

✅ 学习检查点

完成Part 6后,您应该能:

  1. 解释MCP三要素的区别

    • Resources(只读数据) vs Tools(可执行操作) vs Prompts(Prompt模板)
    • 每个要素的典型使用场景
  2. 设计符合JSON Schema规范的工具定义

    • 必填/可选字段
    • 类型系统(string/number/boolean/array/object)
    • 描述写清楚"做什么+副作用+错误"
  3. 理解"解耦"思想,设计可复用的Skill

    • 工具定义与LLM应用分离
    • 一个工具可以被多个应用复用
    • 权限隔离、审计日志
  4. 用Python实现一个简单的MCP Server

    • 响应 tools/listtools/call
    • 路由到不同的工具函数
    • 错误处理
  5. 评估MCP的价值和局限

    • 为什么是大势所趋(生态整合)
    • 当前不足(复杂度、调试难)
    • 适用场景(企业内部工具标准化)

📚 延伸阅读

  • MCP规范文档:https://github.com/context-labs/mcp (GitHub官方)
  • Claude Code Skill开发:https://docs.anthropic.com/en/docs/claude-code/skills
  • OpenCode Skills:https://github.com/opencodeai/opencode/tree/main/docs/skills
  • JSON-RPC 2.0:http://www.jsonrpc.org/specification
  • MCP Server示例集:https://github.com/modelcontextprotocol/servers

Part 6 结束!
MCP是AI应用基础设施的"USB标准",理解它才能构建可扩展、可复用的工具生态。
下一部分 Part 7:微调技术通俗解析 —— 什么场景真正需要微调?如何用LoRA低成本定制领域专家模型?

学习节奏:Part 6建议1.5周,动手实现至少一个MCP Server(哪怕最简单的),理解Client-Server消息流。


系列进度

  • ✅ Part 1:Transformer原理大白话
  • ✅ Part 2:分词与词向量详解
  • ✅ Part 3:提示词工程实战
  • ✅ Part 4:RAG检索增强生成
  • ✅ Part 5:Agent智能体架构
  • ✅ Part 6:MCP协议与Skills系统(当前)
  • 🔄 Part 7:微调技术通俗解析
  • 🔄 Part 8:推理优化与工程部署
  • 🔄 Part 9:综合项目实战与职业发展

工程思维:Part 6是"基础设施层"。在企业落地AI时,工具分散在不同系统(CRM/ERP/DB),MCP提供统一接入层,是规模化应用的前提。值得深入!

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区