(十五)MCP协议与插件生态 --- 扩展无限可能
系列第15篇
作者:挖AI金矿
1.从"重复造轮子"到"标准化插件"
如果你用过前几代的AI编码助手,一定遇到过这个痛点:每个工具都有自己的插件规范,A平台的插件不能用在B平台上。给Claude写了一个文件操作插件,换个模型就不能用了;给Cursor写了一个数据库工具,转到Windsurf又要重写。
后端开发者对这种"各自为政"的生态太熟悉了------就像Node.js出现之前的JavaScript社区,每个框架都有自己的模块加载方式,互不兼容。
MCP(Model Context Protocol)的出现,就是为了解决这个问题。
它的目标很简单:统一AI模型与外部工具、数据源的通信协议,让任何MCP兼容的模型都可以使用任何MCP兼容的工具。
如果把AI模型比作浏览器,MCP就是HTTP协议,MCP Server就是Web服务器。你不需要关心浏览器是Chrome还是Firefox,只要它支持HTTP,就能访问任何网站。
本文将深入MCP协议的设计原理,展示如何通过Hermes的MCP客户端扩展Agent的能力,并手把手教你接入一个数据库MCP Server。
2.MCP究竟是什么?
2.12.1 协议的本质
MCP 定义了一套标准的通信规范,让AI模型(Host)能够发现、调用外部能力(Server)。协议的三个核心角色:
bash
┌─────────────────┐ ┌──────────────────┐
│ MCP Host │ │ MCP Server │
│ (AI Agent) │◄─────►│ (外部能力) │
│ │ │ │
│ - Hermes │ │ - 数据库查询 │
│ - Claude │ │ - GitHub API │
│ - Cursor │ │ - 文件系统 │
│ - 任何MCP客户端│ │ - Web搜索 │
└─────────────────┘ └──────────────────┘
│
▼
┌─────────────────┐
│ Transport │
│ (通信层) │
│ │
│ - stdio │
│ - SSE │
│ - WebSocket │
└─────────────────┘
2.22.2 核心通信流程
MCP的通信分为三个阶段:
阶段一:能力发现(Capability Discovery)
Host 向 Server 发起 initialize 请求,Server 返回它支持的能力清单:
json
// Host → Server: initialize
{
"jsonrpc": "2.0",
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {
"roots": {"listChanged": true},
"sampling": {}
},
"clientInfo": {
"name": "hermes-agent",
"version": "1.0.0"
}
}
}
// Server → Host: initialized
{
"jsonrpc": "2.0",
"result": {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": {
"list": true,
"call": true
},
"resources": {
"list": true,
"read": true
}
},
"serverInfo": {
"name": "github-mcp-server",
"version": "0.1.0"
}
}
}
阶段二:工具列表
Host 调用 tools/list 获取 Server 提供的所有工具:
json
// Host → Server: tools/list
{
"jsonrpc": "2.0",
"method": "tools/list",
"params": {}
}
// Server → Host: tools/list result
{
"jsonrpc": "2.0",
"result": {
"tools": [
{
"name": "search_repositories",
"description": "搜索GitHub仓库",
"inputSchema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词"
},
"per_page": {
"type": "number",
"description": "每页结果数"
}
},
"required": ["query"]
}
},
{
"name": "get_readme",
"description": "获取仓库的README内容",
"inputSchema": {
"type": "object",
"properties": {
"owner": {"type": "string"},
"repo": {"type": "string"}
},
"required": ["owner", "repo"]
}
}
]
}
}
阶段三:工具调用
Host 调用 tools/call 执行具体操作:
json
// Host → Server: tools/call
{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "search_repositories",
"arguments": {
"query": "hermes-agent",
"per_page": 5
}
}
}
// Server → Host: tools/call result
{
"jsonrpc": "2.0",
"result": {
"content": [
{
"type": "text",
"text": "Found 15 repositories:\n1. hermes-agent/hermes - AI agent for terminal\n2. nous-hermes/nous-hermes - ..."
}
],
"isError": false
}
}
2.32.3 MCP vs 传统插件
MCP的标准化优势很明显:写一次插件,到处运行。就像你的后端服务提供了REST API,任何客户端都可以调用------MCP就是AI领域的REST。
3.Hermes的MCP客户端架构
Hermes Agent 内置了完整的MCP客户端,通过 config.yaml 配置即可启用。
3.13.1 配置结构
yaml
# ~/.hermes/config.yaml
agent:
mcp:
# 全局开关
enabled: true
# MCP Server 配置
servers:
# 每个 Server 的配置
github:
# 传输方式
transport: stdio
# 命令和参数
command: npx
args:
- "@modelcontextprotocol/server-github"
# 环境变量(传递给 MCP Server 进程)
env:
GITHUB_TOKEN: "${GITHUB_TOKEN}"
# Server 配置
config:
# 超时设置
timeout: 30000
# 自动重连
auto_reconnect: true
# 最大重试次数
max_retries: 3
# 工具过滤:只暴露需要的工具
tools:
enabled:
- "search_repositories"
- "get_readme"
- "list_issues"
disabled:
- "delete_repository"
- "update_repository"
database:
transport: stdio
command: npx
args:
- "@modelcontextprotocol/server-postgres"
env:
DATABASE_URL: "${DATABASE_URL}"
# 限制只能查询不能修改
tools:
enabled:
- "query"
- "describe_table"
disabled:
- "execute"
- "insert"
- "update"
- "delete"
- "create_table"
- "drop_table"
filesystem:
transport: stdio
command: npx
args:
- "@modelcontextprotocol/server-filesystem"
- "/home/zyw/sandbox"
tools:
disabled:
- "write_file"
- "delete_file"
3.23.2 启动与验证
配置好之后,启动Hermes并验证MCP连接:
bash
# 启动 Hermes
$ hermes
# Agent 启动时会自动加载 MCP Server
# 你会看到类似这样的日志:
[INFO] MCP Server 'github' connected successfully
[INFO] MCP Server 'database' connected successfully
[INFO] MCP Server 'filesystem' connected successfully
[INFO] Available MCP tools:
- github: search_repositories, get_readme, list_issues, create_issue
- database: query, describe_table
- filesystem: read_file, list_directory, search_files
3.33.3 运行时诊断
如果某个Server连接失败,可以用诊断命令排查:
bash
# 查看所有 MCP Server 的状态
$ hermes mcp status
# 输出示例:
MCP Servers Status:
github ● Connected (uptime: 2h 15m)
database ● Connected (uptime: 1h 30m)
filesystem ✗ Disconnected (last error: EACCES: permission denied)
# 查看某个 Server 的详细信息
$ hermes mcp inspect github
# 重启某个 Server
$ hermes mcp restart database
4.mcporter CLI:动态MCP服务管理
除了在 config.yaml 中静态配置,Hermes还提供了一个强大的CLI工具 mcporter,用于动态管理MCP Server。
4.14.1 安装 mcporter
bash
# mcporter 已经集成在 Hermes 中
$ which mcporter
/home/zyw/.hermes/bin/mcporter
# 验证版本
$ mcporter --version
mcporter v1.2.0
4.24.2 常用命令
bash
# 列出所有可用的 MCP Server
$ mcporter list
# 输出示例:
Available MCP Servers:
NAME DESCRIPTION STATUS
github GitHub API integration installed
postgres PostgreSQL database installed
filesystem File system operations installed
brave-search Web search via Brave installed
docker Docker container mgmt not installed
redis Redis database not installed
# 安装一个新的 MCP Server
$ mcporter install @modelcontextprotocol/server-redis
# 启动 Server
$ mcporter start redis
# 停止 Server
$ mcporter stop redis
# 查看 Server 日志
$ mcporter logs redis --tail 20
# 卸载 Server
$ mcporter uninstall redis
# 更新所有 Server
$ mcporter update --all
4.34.3 高级用法:动态注入配置
bash
# 启动时注入环境变量
$ mcporter start postgres \
--env DATABASE_URL="postgresql://user:pass@localhost:5432/mydb" \
--env PGSSLMODE=require
# 动态限制可用工具
$ mcporter start github \
--allow-tools search_repositories,get_readme,list_issues \
--deny-tools delete_repository
# 设置资源配额
$ mcporter start filesystem \
--max-memory 256MB \
--timeout 30s \
--max-requests 1000
4.44.4 脚本化管理
可以将 mcporter 集成到项目启动脚本中:
bash
#!/bin/bash
# start-mcp-servers.sh
echo "Starting MCP Servers..."
# 启动数据库 Server
mcporter start postgres \
--env DATABASE_URL="postgresql://localhost:5432/devdb" \
--allow-tools query,describe_table
# 启动 GitHub Server
mcporter start github \
--env GITHUB_TOKEN="$(cat ~/.config/github/token)" \
--allow-tools search_repositories,list_issues,list_prs
# 启动 Web 搜索 Server
mcporter start brave-search \
--env BRAVE_API_KEY="$(cat ~/.config/brave/api_key)"
echo "All MCP Servers started. Use 'mcporter list' to verify."
5.实战:接入GitHub MCP Server
这是用得最多的场景之一。让Agent直接操作GitHub,从搜索仓库到创建Issue、管理PR。
5.15.1 安装与配置
bash
# 安装 GitHub MCP Server
$ npm install -g @modelcontextprotocol/server-github
# 验证安装
$ npx @modelcontextprotocol/server-github --version
1.0.0
# 获取 GitHub Token
# 在 GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
# 创建 Token,至少需要 repo 和 issues 权限
$ export GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
配置到 Hermes:
yaml
# ~/.hermes/config.yaml
agent:
mcp:
servers:
github:
transport: stdio
command: npx
args:
- "@modelcontextprotocol/server-github"
env:
GITHUB_TOKEN: "${GITHUB_TOKEN}"
config:
timeout: 30000
auto_reconnect: true
5.25.2 使用场景演示
启动Hermes后,可以直接用自然语言操作GitHub:
bash
你:搜索 Hermes Agent 相关的开源项目
Agent 调用: search_repositories(query="hermes-agent")
返回结果:
Found 20 repositories. 主要项目包括:
1. hermes-agent/hermes - AI agent that works in your terminal
2. NousResearch/hermes - Hermes training framework
...
你:查看 hermes-agent/hermes 的 README
Agent 调用: get_readme(owner="hermes-agent", repo="hermes")
返回结果: [README 内容]
你:帮我看看最近5个未解决的Issue
Agent 调用: list_issues(owner="hermes-agent", repo="hermes", state="open", per_page=5)
返回结果: [最近的5个Issue]
5.35.3 高级场景:自动处理Issue
通过MCP,Agent可以完成复杂的Issue处理流程:
bash
你:帮我处理这个Issue #42,它是一个关于"添加Docker支持"的feature request。
先看看Issue内容,然后创建一个对应的milestone。
Agent:
步骤1: get_issue(owner="my-org", repo="my-project", issue_number=42)
步骤2: 分析Issue内容是feature request
步骤3: create_milestone(owner="my-org", repo="my-project", title="Docker Support", due_date="2026-05-01")
步骤4: create_comment(owner="my-org", repo="my-project", issue_number=42, body="Thanks! Created milestone 'Docker Support' for tracking.")
6.实战:接入数据库MCP Server
这是后端开发者最实用的场景。让Agent安全地查询数据库、分析数据。
6.16.1 安装 PostgreSQL MCP Server
bash
# 安装 PostgreSQL MCP Server
$ npm install -g @modelcontextprotocol/server-postgres
# 验证
$ npx @modelcontextprotocol/server-postgres --version
1.0.0
# 准备数据库连接字符串
$ export DATABASE_URL="postgresql://dev_user:dev_pass@localhost:5432/devdb"
6.26.2 安全优先的配置
数据库操作是高风险场景,必须严格限制:
yaml
# ~/.hermes/config.yaml
agent:
mcp:
servers:
postgres:
transport: stdio
command: npx
args:
- "@modelcontextprotocol/server-postgres"
env:
DATABASE_URL: "${DATABASE_URL}"
# 只开放只读工具
tools:
enabled:
- "query" # 执行只读查询
- "describe_table" # 查看表结构
- "list_tables" # 列出所有表
disabled:
- "execute" # 禁止执行任意SQL
- "insert" # 禁止插入
- "update" # 禁止更新
- "delete" # 禁止删除
- "create_table" # 禁止建表
- "drop_table" # 禁止删表
- "alter_table" # 禁止改表
# 额外的查询安全策略
config:
# 只允许 SELECT 查询
readonly: true
# 限制返回行数
max_rows: 1000
# 超时
query_timeout: 10000
6.36.3 实际使用
bash
你:帮我看一下 users 表的结构
Agent 调用: describe_table(table_name="users")
返回:
id SERIAL PRIMARY KEY
name VARCHAR(100)
email VARCHAR(200) UNIQUE
created_at TIMESTAMP DEFAULT NOW()
status VARCHAR(20) DEFAULT 'active'
你:查询最近注册的10个用户
Agent 调用: query(sql="SELECT id, name, email, created_at FROM users ORDER BY created_at DESC LIMIT 10")
返回: [10条用户记录]
6.46.4 安全查询的最佳实践
由于我们限制了只读,Agent只能执行SELECT。但即使如此,也要注意:
sql
-- ❌ 危险的 SELECT(虽然不会修改数据,但可能造成性能问题)
SELECT * FROM orders WHERE amount > 1000000
-- 如果表很大,全表扫描会拖垮数据库
SELECT * FROM users CROSS JOIN orders CROSS JOIN products
-- 笛卡尔积可能产生天文数字的行数
为了防止这类问题,可以在数据库层面设置 statement_timeout:
sql
-- 在数据库中设置
ALTER DATABASE devdb SET statement_timeout = '10s';
或者在MCP Server配置中增加查询验证:
yaml
config:
# 禁止不带 WHERE 的全表查询
require_where_clause: true
# 禁止 JOIN 超过 3 个表
max_joins: 3
# 禁止子查询嵌套超过 2 层
max_subquery_depth: 2
7.MCP社区生态一览
MCP虽然是新生事物,但生态已经相当丰富。截至2026年4月,官方和社区贡献的MCP Server超过200个。
7.17.1 官方维护的Server
7.27.2 社区贡献的有趣Server
bash
# 安装社区 Server
$ mcporter install @anthropic/mcp-server-slack
$ mcporter install @anthropic/mcp-server-notion
$ mcporter install @datadog/mcp-server-datadog
$ mcporter install @aws/mcp-server-dynamodb
$ mcporter install @redis/mcp-server-redis
$ mcporter install @elastic/mcp-server-elasticsearch
$ mcporter install @mongodb/mcp-server-mongodb
社区生态的亮点:
开发工具类:
mcp-server-docker--- 操作Docker容器和镜像mcp-server-kubernetes--- 管理Kubernetes资源mcp-server-terraform--- 管理基础设施mcp-server-aws--- AWS资源管理
数据类:
mcp-server-redis--- Redis缓存查询mcp-server-elasticsearch--- Elasticsearch搜索mcp-server-mongodb--- MongoDB查询mcp-server-clickhouse--- ClickHouse分析
协作类:
mcp-server-slack--- Slack消息和频道管理mcp-server-notion--- Notion文档管理mcp-server-jira--- Jira Issue管理mcp-server-confluence--- Confluence页面管理
自定义Server:
你可以用任何语言实现MCP Server。Python示例:
python
# my_mcp_server.py
import json
import sys
from typing import Any
class MyMCPTool:
"""一个简单的自定义 MCP Server"""
def handle_request(self, request: dict) -> dict:
method = request.get("method")
if method == "initialize":
return {
"protocolVersion": "2025-03-26",
"capabilities": {
"tools": {"list": True, "call": True}
},
"serverInfo": {
"name": "my-custom-server",
"version": "0.0.1"
}
}
elif method == "tools/list":
return {
"tools": [
{
"name": "greet",
"description": "Say hello to someone",
"inputSchema": {
"type": "object",
"properties": {
"name": {"type": "string"}
},
"required": ["name"]
}
},
{
"name": "current_time",
"description": "Get current time in a timezone",
"inputSchema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"default": "Asia/Shanghai"
}
}
}
}
]
}
elif method == "tools/call":
name = request["params"]["name"]
args = request["params"]["arguments"]
if name == "greet":
return {
"content": [{
"type": "text",
"text": f"Hello, {args['name']}! 👋"
}]
}
elif name == "current_time":
from datetime import datetime
import pytz
tz = pytz.timezone(args.get("timezone", "Asia/Shanghai"))
now = datetime.now(tz)
return {
"content": [{
"type": "text",
"text": f"Current time: {now.strftime('%Y-%m-%d %H:%M:%S %Z')}"
}]
}
return {"error": {"code": -32601, "message": "Method not found"}}
def run(self):
"""Stdio transport loop"""
for line in sys.stdin:
try:
request = json.loads(line.strip())
response = self.handle_request(request)
print(json.dumps(response), flush=True)
except Exception as e:
print(json.dumps({"error": {"message": str(e)}}), flush=True)
if __name__ == "__main__":
server = MyMCPTool()
server.run()
注册这个自定义Server:
yaml
agent:
mcp:
servers:
my-custom:
transport: stdio
command: python
args:
- "/home/zyw/mcp-servers/my_mcp_server.py"
8.MCP的安全考量
MCP带来了强大的扩展能力,但也引入了新的安全风险。
8.18.1 风险矩阵
8.28.2 安全配置建议
yaml
agent:
mcp:
# 全局安全设置
security:
# 禁止未签名的 Server
require_signed_servers: true
# Server 签名验证
allowed_publishers:
- "@modelcontextprotocol"
- "@anthropic"
# 沙箱模式:每个 Server 运行在隔离进程中
sandbox: true
# 网络访问控制
network:
# 禁止 Server 访问内网
deny_private_ips: true
# 允许的外网域名白名单
allowed_domains:
- "api.github.com"
- "*.github.com"
# 数据流审计
audit:
log_all_requests: true
log_all_responses: false # 响应可能包含敏感数据
8.38.3 最小工具原则
就像前一篇文章强调的最小权限,MCP Server也要遵循最小工具原则:
yaml
agent:
mcp:
servers:
github:
# 只暴露当前任务需要的工具
tools:
enabled:
- "search_repositories"
- "get_readme"
# 明确禁用有破坏性的工具
disabled:
- "delete_repository"
- "transfer_ownership"
- "create_repository"
- "update_repository"
- "fork_repository"
9.MCP vs 内置工具:何时用哪个?
这是很多开发者的疑问。Hermes既有内置工具(terminal、read_file等),又有MCP扩展,什么时候用哪个?
经验法则:
- 操作本机资源 → 内置工具
- 操作远程服务 → MCP Server
- 需要快速原型 → MCP Server(开箱即用)
- 需要精细控制 → 内置工具
10.实战:搭建一个全能MCP生态
让我们把所有知识串起来,搭建一个后端开发者的全能MCP环境。
10.110.1 完整配置
yaml
# ~/.hermes/config.yaml
agent:
mcp:
enabled: true
servers:
# 代码管理
github:
transport: stdio
command: npx
args: ["@modelcontextprotocol/server-github"]
env:
GITHUB_TOKEN: "${GITHUB_TOKEN}"
tools:
disabled:
- "delete_repository"
- "transfer_ownership"
# 数据库查询
postgres:
transport: stdio
command: npx
args: ["@modelcontextprotocol/server-postgres"]
env:
DATABASE_URL: "postgresql://dev:dev@localhost:5432/devdb"
config:
readonly: true
max_rows: 1000
# 缓存查询
redis:
transport: stdio
command: npx
args: ["@modelcontextprotocol/server-redis"]
env:
REDIS_URL: "redis://localhost:6379"
tools:
enabled:
- "get"
- "keys"
- "exists"
- "ttl"
disabled:
- "set"
- "del"
- "flush"
- "expire"
# 日志搜索
elasticsearch:
transport: stdio
command: npx
args: ["@modelcontextprotocol/server-elasticsearch"]
env:
ELASTICSEARCH_URL: "http://localhost:9200"
config:
max_results: 100
# 文档搜索
brave-search:
transport: stdio
command: npx
args: ["@modelcontextprotocol/server-brave-search"]
env:
BRAVE_API_KEY: "${BRAVE_API_KEY}"
10.210.2 启动脚本
bash
#!/bin/bash
# start-dev-environment.sh
echo "🚀 Starting MCP Servers..."
# 检查依赖
command -v npx >/dev/null 2>&1 || { echo "需要安装 Node.js"; exit 1; }
# 启动所有 Server
mcporter start github --allow-tools search_repositories,list_issues,list_prs
mcporter start postgres --env DATABASE_URL="postgresql://localhost:5432/devdb" --readonly
mcporter start redis --allow-tools get,keys,exists,ttl
mcporter start brave-search
echo ""
echo "✅ All MCP Servers started!"
echo "Type 'hermes' to begin"
echo "Type 'mcporter list' to check status"
10.310.3 工作流示例
配置好之后,你的工作流可以变成这样:
bash
你:帮我排查一下生产环境的问题,用户反馈登录响应慢
Agent:
1. 查询Github(搜索相关Issue和PR)
2. 查询Postgres(分析数据库查询性能)
3. 查询Redis(检查缓存命中率)
4. 查询Elasticsearch(搜索应用日志中的错误)
最终输出一份诊断报告,定位到问题原因
以前需要打开5个不同的工具才能完成的事情,现在一句话就能搞定。
11.写在最后
MCP协议正在重塑AI Agent的生态格局。它带来的不仅仅是技术上的标准化,更是思维方式的转变------从"写死工具"到"动态发现能力",从"孤立运行"到"互联互通"。
对于后端开发者来说,MCP是一个天然契合的技术范式。我们对API设计、协议定义、服务治理的理解,可以直接迁移到MCP Server的开发中。
MCP的核心价值可以归结为三句话:
- 写一次,到处运行 --- Server开发一次,任何MCP Host都能用
- 能力动态发现 --- Host不需要预知Server的能力,运行时自动发现
- 安全边界清晰 --- 每个Server有独立的权限和资源隔离
下一步的演进方向:
- MCP Server市场(像VSCode插件市场一样发现和安装)
- 联邦式MCP(多个Agent共享MCP Server实例)
- MCP Server的SLA和监控
下一篇文章,我们将探讨Hermes的另一个强大功能------Cron任务自动化,让AI定时帮你干活。
作者:挖AI金矿
系列:Hermes Agent 从小白到高级 --- 第 15/18 篇
下一篇:第16篇:Cron任务自动化 --- 让AI定时帮你干活