(十五)MCP协议与插件生态 — 扩展无限可能
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.1 2.1 协议的本质
MCP 定义了一套标准的通信规范,让AI模型(Host)能够发现、调用外部能力(Server)。协议的三个核心角色:
bash┌─────────────────┐ ┌──────────────────┐│ MCP Host │ │ MCP Server ││ (AI Agent) │◄─────►│ (外部能力) ││ │ │ ││ - Hermes │ │ - 数据库查询 ││ - Claude │ │ - GitHub API ││ - Cursor │ │ - 文件系统 ││ - 任何MCP客户端│ │ - Web搜索 │└─────────────────┘ └──────────────────┘ │ ▼┌─────────────────┐│ Transport ││ (通信层) ││ ││ - stdio ││ - SSE ││ - WebSocket │└─────────────────┘
2.2 2.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.3 2.3 MCP vs 传统插件
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MCP的标准化优势很明显:写一次插件,到处运行。就像你的后端服务提供了REST API,任何客户端都可以调用——MCP就是AI领域的REST。
3. 三、Hermes的MCP客户端架构
Hermes Agent 内置了完整的MCP客户端,通过 config.yaml 配置即可启用。
3.1 3.1 配置结构
yaml# ~/.hermes/config.yamlagent:mcp:# 全局开关enabled:true# MCP Server 配置servers:# 每个 Server 的配置github:# 传输方式transport:stdio# 命令和参数command:npxargs:-"@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:stdiocommand:npxargs:-"@modelcontextprotocol/server-postgres"env:DATABASE_URL:"${DATABASE_URL}"# 限制只能查询不能修改tools:enabled:-"query"-"describe_table"disabled:-"execute"-"insert"-"update"-"delete"-"create_table"-"drop_table"filesystem:transport:stdiocommand:npxargs:-"@modelcontextprotocol/server-filesystem"-"/home/zyw/sandbox"tools:disabled:-"write_file"-"delete_file"
3.2 3.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.3 3.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.1 4.1 安装 mcporter
bash# mcporter 已经集成在 Hermes 中$ which mcporter/home/zyw/.hermes/bin/mcporter# 验证版本$ mcporter --versionmcporter v1.2.0
4.2 4.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.3 4.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.4 4.4 脚本化管理
可以将 mcporter 集成到项目启动脚本中:
bash#!/bin/bash# start-mcp-servers.shecho"Starting MCP Servers..."# 启动数据库 Servermcporter start postgres \ --env DATABASE_URL="postgresql://localhost:5432/devdb" \ --allow-tools query,describe_table# 启动 GitHub Servermcporter start github \ --env GITHUB_TOKEN="$(cat ~/.config/github/token)" \ --allow-tools search_repositories,list_issues,list_prs# 启动 Web 搜索 Servermcporter 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.1 5.1 安装与配置
bash# 安装 GitHub MCP Server$ npm install -g @modelcontextprotocol/server-github# 验证安装$ npx @modelcontextprotocol/server-github --version1.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.yamlagent:mcp:servers:github:transport:stdiocommand:npxargs:-"@modelcontextprotocol/server-github"env:GITHUB_TOKEN:"${GITHUB_TOKEN}"config:timeout:30000auto_reconnect:true
5.2 5.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 terminal2. NousResearch/hermes - Hermes training framework...你:查看 hermes-agent/hermes 的 READMEAgent 调用: get_readme(owner="hermes-agent", repo="hermes")返回结果: [README 内容]你:帮我看看最近5个未解决的IssueAgent 调用: list_issues(owner="hermes-agent", repo="hermes", state="open", per_page=5)返回结果: [最近的5个Issue]
5.3 5.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.1 6.1 安装 PostgreSQL MCP Server
bash# 安装 PostgreSQL MCP Server$ npm install -g @modelcontextprotocol/server-postgres# 验证$ npx @modelcontextprotocol/server-postgres --version1.0.0# 准备数据库连接字符串$ export DATABASE_URL="postgresql://dev_user:dev_pass@localhost:5432/devdb"
6.2 6.2 安全优先的配置
数据库操作是高风险场景,必须严格限制:
yaml# ~/.hermes/config.yamlagent:mcp:servers:postgres:transport:stdiocommand:npxargs:-"@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.3 6.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.4 6.4 安全查询的最佳实践
由于我们限制了只读,Agent只能执行SELECT。但即使如此,也要注意:
sql-- ❌ 危险的 SELECT(虽然不会修改数据,但可能造成性能问题)SELECT*FROM orders WHERE amount >1000000-- 如果表很大,全表扫描会拖垮数据库SELECT*FROM users CROSSJOIN orders CROSSJOIN products-- 笛卡尔积可能产生天文数字的行数
为了防止这类问题,可以在数据库层面设置 statement_timeout:
sql-- 在数据库中设置ALTER DATABASE devdb SET statement_timeout ='10s';
或者在MCP Server配置中增加查询验证:
yamlconfig:# 禁止不带 WHERE 的全表查询require_where_clause:true# 禁止 JOIN 超过 3 个表max_joins:3# 禁止子查询嵌套超过 2 层max_subquery_depth:2
7. 七、MCP社区生态一览
MCP虽然是新生事物,但生态已经相当丰富。截至2026年4月,官方和社区贡献的MCP Server超过200个。
7.1 7.1 官方维护的Server
|
|
|
|
|---|---|---|
@modelcontextprotocol/server-github |
|
npx @modelcontextprotocol/server-github |
@modelcontextprotocol/server-postgres |
|
npx @modelcontextprotocol/server-postgres |
@modelcontextprotocol/server-sqlite |
|
npx @modelcontextprotocol/server-sqlite |
@modelcontextprotocol/server-filesystem |
|
npx @modelcontextprotocol/server-filesystem <dir> |
@modelcontextprotocol/server-brave-search |
|
npx @modelcontextprotocol/server-brave-search |
@modelcontextprotocol/server-puppeteer |
|
npx @modelcontextprotocol/server-puppeteer |
@modelcontextprotocol/server-everything |
|
npx @modelcontextprotocol/server-everything |
7.2 7.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.pyimport jsonimport sysfrom typing importAnyclassMyMCPTool:"""一个简单的自定义 MCP Server"""defhandle_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 datetimeimport 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"}}defrun(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:
yamlagent:mcp:servers:my-custom:transport:stdiocommand:pythonargs:-"/home/zyw/mcp-servers/my_mcp_server.py"
8. 八、MCP的安全考量
MCP带来了强大的扩展能力,但也引入了新的安全风险。
8.1 8.1 风险矩阵
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8.2 8.2 安全配置建议
yamlagent:mcp:# 全局安全设置security:# 禁止未签名的 Serverrequire_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:truelog_all_responses:false# 响应可能包含敏感数据
8.3 8.3 最小工具原则
就像前一篇文章强调的最小权限,MCP Server也要遵循最小工具原则:
yamlagent: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.1 10.1 完整配置
yaml# ~/.hermes/config.yamlagent:mcp:enabled:trueservers:# 代码管理github:transport:stdiocommand:npxargs: ["@modelcontextprotocol/server-github"]env:GITHUB_TOKEN:"${GITHUB_TOKEN}"tools:disabled:-"delete_repository"-"transfer_ownership"# 数据库查询postgres:transport:stdiocommand:npxargs: ["@modelcontextprotocol/server-postgres"]env:DATABASE_URL:"postgresql://dev:dev@localhost:5432/devdb"config:readonly:truemax_rows:1000# 缓存查询redis:transport:stdiocommand:npxargs: ["@modelcontextprotocol/server-redis"]env:REDIS_URL:"redis://localhost:6379"tools:enabled:-"get"-"keys"-"exists"-"ttl"disabled:-"set"-"del"-"flush"-"expire"# 日志搜索elasticsearch:transport:stdiocommand:npxargs: ["@modelcontextprotocol/server-elasticsearch"]env:ELASTICSEARCH_URL:"http://localhost:9200"config:max_results:100# 文档搜索brave-search:transport:stdiocommand:npxargs: ["@modelcontextprotocol/server-brave-search"]env:BRAVE_API_KEY:"${BRAVE_API_KEY}"
10.2 10.2 启动脚本
bash#!/bin/bash# start-dev-environment.shecho"🚀 Starting MCP Servers..."# 检查依赖command -v npx >/dev/null 2>&1 || { echo"需要安装 Node.js"; exit 1; }# 启动所有 Servermcporter start github --allow-tools search_repositories,list_issues,list_prsmcporter start postgres --env DATABASE_URL="postgresql://localhost:5432/devdb" --readonlymcporter start redis --allow-tools get,keys,exists,ttlmcporter start brave-searchecho""echo"✅ All MCP Servers started!"echo"Type 'hermes' to begin"echo"Type 'mcporter list' to check status"
10.3 10.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定时帮你干活
夜雨聆风