引言
打开任何一份 AI 行业报告,你都会反复看到四个词:LLM、Agent、Skills、MCP。它们被同时提及的频率越来越高,但很少有人把它们讲清楚——很多教程把 LLM 和 Agent 混为一谈,把 Skills 说成”高级 Prompt”,把 MCP 当成”新版 Function Calling”。
这种混淆带来的直接后果是:你买了一堆工具,读了很多教程,却仍然写不出一个能落地的 AI 应用。因为你不清楚每一层负责什么、层与层之间靠什么接口通信、出了问题该在哪一层排查。
本文不打算重复”什么是大模型”这种科普,而是把四个概念拆成四层架构,用一套贯穿始终的实战案例(自动发布博客)讲清楚:
- LLM 是大脑,负责推理与生成;
- Agent 是大脑加上四肢,负责决策与循环;
- Skills 是肌肉记忆,负责把”怎么做”沉淀成可复用流程;
- MCP 是神经系统,负责让 Agent 安全、标准化地调用外部工具。
读完之后,你应该能自己画出一张架构图,并且知道该给哪一层加什么代码。

一、四个概念各是什么
1. LLM:大脑
LLM(Large Language Model,大语言模型) 是一个在海量文本上训练的神经网络,输入一段文本,输出一段文本。它本身不会上网、不会读文件、不会执行命令——它只会”预测下一个 token”。
关键点:LLM 是无状态的。它不知道你是谁、不知道上次聊到哪、不知道你项目里有哪些文件。所有”记住””执行”的能力,都是在它之外搭起来的。
# LLM 的本质:一个纯函数,输入 token,输出 token
def llm(prompt: str) -> str:
# 没有工具、没有文件、没有网络——只有预测
return "根据您提供的信息,建议您……"
answer = llm("Ubuntu 22.04 怎么升级内核?")
2. Agent:大脑 + 四肢 + 循环
Agent(智能体) 是围绕 LLM 搭建的一个运行循环:用户给目标 → LLM 规划 → 调用工具 → 观察结果 → 再规划 → …… 直到目标完成。
同样是”升级内核”这个需求,LLM 只能输出一段文字建议;Agent 会真的去 ssh 到服务器、执行 apt、检查日志、失败重试,最后回报”已升级到 5.15.0-124″。
区别不在于模型能力,而在于有没有一个循环在持续调用工具并观察结果。
用户目标
│
▼
┌──────────────────────────┐
│ Agent Loop(决策循环) │
│ ┌────────┐ ┌────────┐ │
│ │ LLM │──▶│ Planner│ │
│ │(推理) │◀──│ │ │
│ └────────┘ └───┬────┘ │
│ ▲ │ │
│ │ ▼ │
│ 观察结果 ◀── 工具执行 │
│ (Observation) (Tool Call)│
└──────────────────────────┘
3. Skills:可复用的肌肉记忆
Skills(技能) 是把”完成某类任务的标准流程”写成的结构化文档(通常是一个带 YAML 头部的 Markdown 文件),让 Agent 遇到同类任务时直接照做,而不必每次都重新摸索。
一个 Skill 至少包含:
- 触发条件:什么情况下该用这个技能;
- 步骤:带精确命令的操作序列;
- 坑点(Pitfalls):踩过的失败路径及规避方法;
- 验证方式:怎么确认做对了。
Skill 和 Prompt 的本质区别是:Prompt 是一次性的口头交代,Skill 是沉淀下来的书面 SOP。Prompt 写错了这一次就浪费了;Skill 修一次,之后每次执行都受益。

4. MCP:工具接入的标准协议
MCP(Model Context Protocol,模型上下文协议) 是一套让 LLM/Agent 标准化调用外部工具的协议,本质是 JSON-RPC 2.0 之上的约定。
在它出现之前,每接一个工具都要写一套专属的胶水代码:OpenAI 的 Function Calling、Anthropic 的 Tool Use、各家 SDK 的自定义 schema…… MCP 把这些统一成三种原语:
| 原语 | 方向 | 作用 |
|---|---|---|
tools/list |
客户端 → 服务端 | 服务端宣告”我能提供哪些工具” |
tools/call |
客户端 → 服务端 | 客户端请求执行某个工具 |
resources/* |
双向 | 暴露文档、文件等上下文资源 |
一句话理解:MCP Server 是把工具封装成标准接口的进程,MCP Client 是负责发现和调用的那一方。Agent 只需要连 Client,不需要知道工具背后的实现细节。
5. 四层总览
┌─────────────────────────────────────────┐
│ L1 Skills 可复用流程 / SOP │ ← 解决"怎么做"
├─────────────────────────────────────────┤
│ L2 Agent 决策循环 / 工具编排 │ ← 解决"谁来做"
├─────────────────────────────────────────┤
│ L3 MCP 工具接入标准协议 │ ← 解决"怎么调"
├─────────────────────────────────────────┤
│ L4 LLM 推理与文本生成 │ ← 解决"想什么"
└─────────────────────────────────────────┘
排查问题的方向也是反的:结果不对先看 L2(循环决策是不是错了),工具调用失败看 L3(协议/参数),输出质量差看 L4(模型/Prompt),流程跑偏看 L1(Skill 描述是否准确)。
二、实战:一个 Agent 自动发布博客
下面用一个真实场景把四层串起来:让 Agent 读到 Markdown 稿件,转成 HTML,发布到 WordPress,再把链接回传。
1. Agent 主循环(L2)
Agent 的核心就是一个 while 循环:调用 LLM 决定下一步,执行工具,把结果喂回去。
import json
import subprocess
def agent_loop(goal: str, max_turns: int = 10) -> str:
"""最简 Agent 循环:LLM 规划 + 工具执行 + 观察结果"""
messages = [{"role": "user", "content": goal}]
for turn in range(max_turns):
# 1) LLM 规划下一步(这里抽象掉具体模型调用)
decision = call_llm(messages, tools=TOOL_SCHEMAS)
# 2) 如果没有工具调用,说明任务完成
if not decision.get("tool_calls"):
return decision["content"]
# 3) 执行工具,把结果追加进上下文
for call in decision["tool_calls"]:
result = dispatch_tool(call["name"], call["arguments"])
messages.append({
"role": "tool",
"name": call["name"],
"content": json.dumps(result, ensure_ascii=False),
})
return "达到最大轮次,任务未完成"
这里的 dispatch_tool 就是 L3(MCP)要接管的地方。
2. 加载 Skills(L1)
Agent 启动时扫描技能目录,把命中的 Skill 注入上下文,让 LLM”照着 SOP 做”。
# 扫描可用技能并提取 frontmatter
for skill in /root/.hermes/skills/web-development/wordpress-install; do
echo "=== $(basename $skill) ==="
sed -n '/^---$/,/^---$/p' "$skill/SKILL.md" | head -n 8
done
# 统计技能总数与分类
find /root/.hermes/skills -name 'SKILL.md' | wc -l
find /root/.hermes/skills -mindepth 1 -maxdepth 1 -type d | sort
输出示例:
=== wordpress-install ===
---
name: wordpress-install
description: "安装、配置、管理和发布 WordPress — 包括手动部署、wp-cli 管理、REST API / Direct PHP 自动发文..."
version: 1.0.1
---
72
/root/.hermes/skills/web-development
/root/.hermes/skills/devops
/root/.hermes/skills/research
3. 通过 MCP 调用工具(L3)
Agent 不直接 exec 发布脚本,而是通过 MCP Client 请求一个”publish 工具”。Client 配置文件声明要连哪些 Server:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/wwwroot"],
"transport": "stdio"
},
"wordpress": {
"command": "python3",
"args": ["/root/tools/wp-mcp-server.py"],
"env": { "WP_DIR": "/home/wwwroot/www.stellardata.top" },
"transport": "stdio"
}
}
}
Agent 拿到 tools/list 返回后,会看到类似这样的工具清单:
{
"tools": [
{
"name": "wp_publish_markdown",
"description": "将本地 Markdown 文件转换为 HTML 并发布到 WordPress",
"inputSchema": {
"type": "object",
"properties": {
"path": { "type": "string", "description": "Markdown 文件绝对路径" },
"category": { "type": "string", "description": "WordPress 分类名称" }
},
"required": ["path"]
}
}
]
}
4. MCP 协议的原始报文
MCP 走 JSON-RPC 2.0,一次完整的”列出工具 → 调用工具”长这样:
// 请求:列出可用工具
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
// 响应:调用 publish 工具
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text", "text": "Published: https://www.stellardata.top/?p=3263" }
]
}
}
关键在于:Agent 侧只依赖 tools/list + tools/call 这两个方法名,工具实现在哪台机器、用哪种语言写,它完全不用关心。
5. 客户端与运行时配置
MCP Server 的运行参数通常放在配置文件和环境变量里:
# Hermes Agent 的 MCP 客户端配置片段
mcp:
enabled: true
servers:
wordpress:
command: python3
args: [/root/tools/wp-mcp-server.py]
transport: stdio
timeout: 60
filesystem:
command: npx
args: [-y, "@modelcontextprotocol/server-filesystem", /home/wwwroot]
; MCP Server 运行时配置(.env / INI 风格)
[wordpress]
WP_DIR = /home/wwwroot/www.stellardata.top
POST_AUTHOR = 1
DEFAULT_CATEGORY = IT互联网
FEATURED_IMAGE_ID = 1623
[security]
; 允许 Agent 发布的分类白名单
ALLOWED_CATEGORIES = IT互联网,IT资讯,大数据
; 是否允许覆盖已有文章
ALLOW_OVERWRITE = false
三、动手写一个 MCP Server
理论讲完,下面给一个可直接运行的最小 MCP Server:把”发布 Markdown”暴露成标准工具。
1. Server 实现
#!/usr/bin/env python3
"""最小 WordPress MCP Server:把发布能力暴露为标准 MCP 工具"""
import json
import os
import subprocess
import sys
WP_DIR = os.environ.get("WP_DIR", "/home/wwwroot/www.stellardata.top")
PUBLISH_SH = "/root/.hermes/skills/web-development/wordpress-install/scripts/direct-publish.sh"
TOOLS = [{
"name": "wp_publish_markdown",
"description": "将本地 Markdown 文件发布到 WordPress",
"inputSchema": {
"type": "object",
"properties": {
"path": {"type": "string", "description": "Markdown 文件路径"}
},
"required": ["path"],
},
}]
def handle_publish(args: dict) -> dict:
proc = subprocess.run(
["bash", PUBLISH_SH, args["path"]],
capture_output=True, text=True, cwd=WP_DIR, timeout=120,
)
return {"stdout": proc.stdout, "stderr": proc.stderr, "code": proc.returncode}
def dispatch(request: dict) -> dict:
method = request.get("method")
rid = request.get("id")
if method == "tools/list":
return {"jsonrpc": "2.0", "id": rid, "result": {"tools": TOOLS}}
if method == "tools/call":
name = request["params"]["name"]
args = request["params"]["arguments"]
if name == "wp_publish_markdown":
return {"jsonrpc": "2.0", "id": rid,
"result": {"content": [{"type": "text", "text": json.dumps(handle_publish(args), ensure_ascii=False)}]}}
return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32602, "message": f"unknown tool: {name}"}}
return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32601, "message": f"unknown method: {method}"}}
def main():
for line in sys.stdin:
line = line.strip()
if not line:
continue
sys.stdout.write(json.dumps(dispatch(json.loads(line)), ensure_ascii=False) + "n")
sys.stdout.flush()
if __name__ == "__main__":
main()
2. 本地连通性验证
不启动完整 Agent,直接用管道验证 Server 是否正常响应:
printf '%sn'
'{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
| python3 /root/tools/wp-mcp-server.py | python3 -m json.tool
# 验证 WordPress 环境就绪
cd /home/wwwroot/www.stellardata.top && php -r '
define("WP_USE_THEMES", false);
require("wp-load.php");
echo "WP OK: " . get_bloginfo("name") . "n";
'
# 检查发布脚本可执行
test -x /root/.hermes/skills/web-development/wordpress-install/scripts/direct-publish.sh && echo "publish.sh OK"
3. 端到端调用
# 准备一篇测试稿件
cp /tmp/auto_article.md /tmp/mcp-test-article.md
# 直接调用工具方法,绕过 Agent
printf '%sn'
'{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"wp_publish_markdown","arguments":{"path":"/tmp/mcp-test-article.md"}}}'
| python3 /root/tools/wp-mcp-server.py
执行成功后,result.content[0].text 里会包含发布脚本的 stdout,其中包括文章 ID 与 permalink。
四、常见问题
Q1:LLM 和 Agent 是同一个东西吗?
不是。LLM 是一个模型(一次输入、一次输出、无状态);Agent 是运行 LLM 的循环 + 工具编排层。同一个 GPT-4 或 Qwen,接进不同 Agent 框架后能力差异巨大——差异全部来自 L2,而不是 L4。
Q2:Skills 不就是更长的 Prompt 吗?
表面像,机制不同。Prompt 是本次会话的临时指令;Skill 是持久化、带元数据、可版本管理的流程文档,Agent 会按触发条件按需加载,只在需要时占用上下文。工程上还多出三层价值:可复用(多个 Agent 共享)、可维护(改一次全局生效)、可验证(Skill 里的验证步骤)。
Q3:MCP 会取代 Function Calling 吗?
互补而非替代。Function Calling 是模型层能力(教模型如何吐出结构化参数),MCP 是协议层标准(定义工具如何被发现与调用)。模型输出 Function Calling 格式的 JSON,Agent 再通过 MCP 路由到具体 Server。MCP 解决的是”生态碎片化”,Function Calling 解决的是”模型会不会调”。
Q4:我需要自己写 MCP Server 吗?
看场景。如果只是个人使用现成工具(文件系统、GitHub、Slack),直接用官方 Server 即可。但如果你的核心能力藏在内部系统里(公司 CMS、内网数据库、私有 API),写一个 Server 把能力封装成标准工具,是整个 Agent 体系里 ROI 最高的一步——一次封装,所有 Agent 都能调用。
Q5:Skills 有安全风险吗?
有,而且是供应链风险。Agent 会信任并执行 Skill 里的命令,一个恶意 Skill 等同于给 Agent 一把万能钥匙。三点防御:① 只从可信来源安装 Skill;② 安装前审读全文,尤其是含 rm、curl | sh、凭据读取的步骤;③ 高权限操作(写数据库、发消息、扣费)在 Agent 侧设确认门禁,不要让 Skill 单独决定。
五、总结
- LLM 是大脑:只做推理与生成,无状态、无工具、无记忆。它决定了输出质量的天花板。
- Agent 是循环:真正带来”自动化”的是 LLM 外面的那个 while 循环,不是模型本身。
- Skills 是 SOP:把踩过的坑沉淀成文档,一次修复、长期受益,是 Agent 能力复用的基本单位。
- MCP 是协议:统一工具接入方式,解决生态碎片化,让内部能力一次封装、处处调用。
- 排查顺序自下而上:输出差改 LLM/Prompt,调不动查 MCP,跑偏改 Skill,决策错改 Agent。
如果你只能做一件事,建议从写第一个 MCP Server开始——把你自己每天都要手动干的那个活儿暴露成标准工具,你会立刻理解这四个概念为什么必须一起出现。
















暂无评论内容