预设代码、Skill 与 MCP

本文以我的开源项目 OpsMind 为例,探讨 AI 应用开发中三种常见的技术模式:预设代码、Skill 和 MCP,分析它们的本质区别与适用场景。

最近在开发 OpsMind —— 一个智能运营决策中枢,核心功能是通过自然语言对话进行数据分析和文件生成。在研究 AI 应用架构时,我接触到了 SkillMCP 两个概念。
起初我有些困惑:我的项目也能通过对话生成文件,这和 MCP 有什么区别?预设代码算不算 Skill 技术?这些技术和提示词工程又是什么关系?

我的现状:预设代码模式

项目架构

OpsMind 目前的核心是一个 DataAnalysisEngine 类,所有功能都硬编码在类方法中:

class DataAnalysisEngine:
"""数据分析引擎类"""

def generate_charts(self, df, chart_types):
"""生成图表"""
if "histogram" in chart_types:
plt.hist(...) # 直方图
if "scatter" in chart_types:
plt.scatter(...) # 散点图
if "heatmap" in chart_types:
sns.heatmap(...) # 热力图
# ... 更多图表类型

def generate_tables(self, df, table_types):
"""生成表格"""
if "basic_stats" in table_types:
df.describe().to_excel(...) # 统计表
if "pivot" in table_types:
df.pivot_table(...).to_excel(...) # 透视表
# ... 更多表格类型

执行流程

用户说”帮我分析销售数据并生成图表”,整个流程如下:

┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ 用户输入 │ ──→ │ LLM 判断 │ ──→ │ 调用预设 │ ──→ │ 生成文件 │
│ │ │ 意图 │ │ 函数 │ │ │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘

LLM 的作用是判断用户想要什么类型的图表/表格,然后调用对应的 Python 函数执行。

这种模式的特点

优点 缺点
开发简单,逻辑清晰 功能固定,扩展需改代码
性能好,无额外开销 无法被其他 AI 应用复用
功能可控,调试方便 所有功能耦合在一起

我把这种模式称为预设代码模式——功能写死在代码里,调用时直接执行。


Skill 技术:动态能力注入

什么是 Skill

Skill 是一种运行时动态加载能力的模式。与预设代码不同,Skill 不是把所有功能都写死在启动时加载,而是根据用户需求,按需激活对应的能力模块。

如果用 Skill 重构 OpsMind

skills/
├── data_analysis/
│ └── skill.md # 数据分析能力
├── chart_generation/
│ └── skill.md # 图表生成能力
└── table_export/
└── skill.md # 表格导出能力

每个 Skill 文件包含:

# 图表生成 Skill

## 触发条件
用户要求生成图表、可视化数据时激活

## Prompt 模板
你是一个数据可视化专家,可以生成以下图表:
- 直方图:调用 generate_histogram(data, column)
- 散点图:调用 generate_scatter(data, x_col, y_col)
- 热力图:调用 generate_heatmap(data, columns)

## 工具定义
- generate_histogram(data, column): 生成指定列的直方图
- generate_scatter(data, x_col, y_col): 生成散点图
- generate_heatmap(data, columns): 生成相关性热力图

执行流程对比

预设代码模式:

启动时加载所有功能 → 用户提问 → LLM 选择函数 → 执行

Skill 模式:

启动时加载基础能力 → 用户提问 → 识别需要哪个 Skill → 动态注入 Skill → LLM 使用 Skill 中的工具 → 执行

与预设代码的对比

维度 预设代码 Skill
加载时机 启动时全部加载 运行时按需加载
Prompt 位置 固定在代码里 动态注入上下文
扩展方式 修改源代码 添加 Skill 文件
隔离性 功能耦合 模块独立
复用性 仅限本项目 可跨项目复用

我的理解:Skill 本质上是把”能力”抽象成可插拔的模块,让 AI Agent 能够根据任务动态组装自己的能力集。


MCP:跨应用工具共享协议

什么是 MCP

MCP(Model Context Protocol)是 Anthropic 推出的开放协议,让 AI 应用能够调用外部工具。与 Skill 不同,MCP 关注的是跨应用的能力共享

如果用 MCP 重构 OpsMind

我可以把数据分析能力封装成 MCP Server:

# mcp_server.py
from mcp import Server

server = Server("opsmind-data-analysis")

@server.tool("analyze_excel")
def analyze_excel(file_path: str, query: str) -> dict:
"""
分析 Excel 文件并返回结果

Args:
file_path: Excel 文件路径
query: 分析需求描述

Returns:
包含分析结果的字典
"""
df = pd.read_excel(file_path)
# 分析逻辑...
return {"result": analysis_result}

@server.tool("generate_chart")
def generate_chart(data_path: str, chart_type: str, columns: list) -> str:
"""
生成图表并返回文件路径

Args:
data_path: 数据文件路径
chart_type: 图表类型 (histogram/scatter/heatmap)
columns: 要分析的列名

Returns:
生成的图表文件路径
"""
# 图表生成逻辑...
return chart_path

MCP 的核心价值

┌─────────────────────────────────────────────────────────────┐
│ MCP 生态 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Claude │ │ Cursor │ │ Trae │ │
│ │ (Client) │ │ (Client) │ │ (Client) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └─────────────────┼─────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ MCP Protocol │ │
│ └────────┬────────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ OpsMind │ │ 文件系统 │ │ 数据库 │ │
│ │ (Server) │ │ (Server) │ │ (Server) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

这样,任何支持 MCP 的 AI 应用都能直接使用 OpsMind 的数据分析工具,无需重复开发。

与 Skill 的对比

维度 Skill MCP
作用范围 单个 AI 应用内部 跨应用共享
工具位置 应用内 独立进程
协议标准 无统一标准 统一开放协议
适用场景 能力模块化 工具生态化
开发成本 较低 需要实现协议

我的理解:MCP 解决的是”工具孤岛”问题——让不同 AI 应用能够共享同一套工具,而不是每个应用都重复开发。


三者的本质区别

架构对比图

┌─────────────────────────────────────────────────────────────────┐
│ │
│ 【预设代码】 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ AI 应用 │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ 功能 A │ │ 功能 B │ │ 功能 C │ ← 全部硬编码 │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 【Skill】 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ AI 应用 │ │
│ │ ┌─────────┐ │ │
│ │ │ 基础能力 │ ←── 动态加载 ───┐ │ │
│ │ └─────────┘ │ │ │
│ └───────────────────────────────┼─────────────────────────┘ │
│ │ │
│ ┌───────────────┬───────────────┴───────────────┐ │
│ │ Skill A │ Skill B │ Skill C │ │
│ │ (按需加载) │ (按需加载) │ (按需加载) │ │
│ └───────────────┴───────────────┴───────────────┘ │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 【MCP】 │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ AI 应用 A │ │ AI 应用 B │ │
│ │ (MCP Client) │ │ (MCP Client) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ └───────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ MCP Protocol │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │MCP Server │ │MCP Server │ │MCP Server │ │
│ │ (工具1) │ │ (工具2) │ │ (工具3) │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

核心差异总结

维度 预设代码 Skill MCP
设计目标 快速实现功能 模块化能力管理 跨应用工具共享
工具位置 应用内部 应用内部 独立进程
加载方式 启动时全部加载 运行时按需加载 通过协议调用
扩展方式 修改源代码 添加 Skill 文件 连接新 Server
共享能力 无法共享 应用内共享 跨应用共享
开发成本
适用规模 小型项目 中型项目 大型生态

提示词与执行层的关系

一个关键问题

在研究这些技术时,我曾有一个疑问:这些技术都可以算是集成的提示词吗?

答案是:不完全是,但都和提示词相关。

分层理解

┌─────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ LLM(大语言模型) │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 【提示词层】决定 LLM 知道什么 │ │
│ │ │ │
│ │ - 告诉 LLM 有哪些能力可用 │ │
│ │ - 告诉 LLM 如何调用这些能力 │ │
│ │ - 告诉 LLM 参数格式和返回格式 │ │
│ └─────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 【执行层】决定实际做什么 │ │
│ │ │ │
│ │ - 预设代码:应用内的 Python 函数 │ │
│ │ - Skill:应用内的模块化函数 │ │
│ │ - MCP:外部独立进程 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘

以 OpsMind 为例

预设代码模式:

# 提示词部分:告诉 LLM 有哪些图表类型可选
prompt = """
【可选图表类型】
- histogram: 直方图 - 查看数值分布
- scatter: 散点图 - 查看变量关系
- heatmap: 热力图 - 查看特征相关性
"""

# 执行部分:Python 代码直接执行
if "histogram" in chart_types:
plt.hist(...) # ← 这不是提示词,是真正的代码执行

Skill 模式:

<!-- skill.md - 这部分会转换成提示词注入给 LLM -->
# 图表生成 Skill

你是一个数据可视化专家,可以生成以下图表:
- 直方图:调用 generate_histogram(data, column)
- 散点图:调用 generate_scatter(data, x_col, y_col)

<!-- 实际执行的函数定义在别处 -->

MCP 模式:

# MCP Server 定义工具
@server.tool("generate_chart")
def generate_chart(data_path: str, chart_type: str) -> str:
"""生成图表并返回文件路径""" # ← 这个描述会变成提示词
# 实际执行代码
return chart_path

# LLM 收到的提示词:
# 你可以使用以下工具:
# - generate_chart: 生成图表,参数:data_path, chart_type

形象比喻

概念 比喻 作用
提示词 菜单 告诉客人(LLM)有什么菜
预设代码/Skill/MCP 厨房 真正做菜的地方

关键理解

  • 提示词是 LLM 的”说明书”——告诉它能做什么
  • 预设代码/Skill/MCP 是执行层——真正干活的代码
  • 这三种技术都依赖提示词让 LLM 知道有什么能力可用,但不是提示词本身

技术选型建议

场景匹配

场景 推荐模式 理由
快速开发 MVP 预设代码 开发成本低,迭代快
功能相对固定 预设代码 无需复杂架构
需要模块化扩展 Skill 能力可插拔,易维护
多团队协作开发 Skill 模块独立,职责清晰
需要跨应用共享工具 MCP 一次开发,多处使用
构建工具生态 MCP 开放协议,生态共赢

OpsMind 的演进方向

目前 OpsMind 使用预设代码模式,对于单一应用来说已经足够。但未来可以考虑:

┌─────────────────────────────────────────────────────────────┐
│ OpsMind 架构演进 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 第一阶段:预设代码(当前) │
│ ├── 快速实现核心功能 │
│ ├── 验证产品价值 │
│ └── 积累用户反馈 │
│ │
│ 第二阶段:引入 Skill │
│ ├── 模块化现有功能 │
│ ├── 支持第三方 Skill 扩展 │
│ └── 提升可维护性 │
│ │
│ 第三阶段:MCP Server │
│ ├── 开放数据分析能力给其他 AI 应用 │
│ ├── 接入 MCP 生态 │
│ └── 构建工具生态 │
│ │
└─────────────────────────────────────────────────────────────┘

组合使用

三者并非互斥,可以组合使用:

AI 应用 → Skill(动态加载能力)→ MCP Client → MCP Server(调用外部工具)

例如:

  • OpsMind 作为 AI 应用
  • 使用 Skill 管理内部能力模块
  • 通过 MCP Client 连接外部工具(如数据库、文件系统)
  • 同时作为 MCP Server 对外提供服务

总结

核心观点

  1. 预设代码:功能写死在代码里,简单直接,适合快速开发和功能固定的场景。

  2. Skill:动态能力注入,按需加载,适合模块化设计和需要扩展的场景。

  3. MCP:跨应用工具共享,开放协议,适合构建工具生态和跨应用复用。

  4. 提示词与执行层:提示词是 LLM 的”说明书”,预设代码/Skill/MCP 是真正干活的”执行层”,两者配合才能让 AI 应用具备实际能力。

架构演进路径

预设代码 → Skill → MCP
↓ ↓ ↓
功能固定 能力模块化 工具生态化
↓ ↓ ↓
单应用内 单应用内 跨应用共享
↓ ↓ ↓
改代码扩展 加文件扩展 连接新Server

最后的话

没有最好的架构,只有最适合的架构。理解每种模式的适用场景,才能做出正确的技术选型。

对于 OpsMind 这样的项目,从预设代码开始是正确的选择——先验证价值,再考虑架构演进。当功能逐渐丰富、用户需求多样化时,再引入 Skill 和 MCP,逐步构建更开放、更可扩展的架构。