MCP 服务标准(ourmcp)
架构总览
用户/Agent
│
├─ HTTPS ── Traefik (capitaltrain.cn) ── Streamable HTTP MCP Server
│ (consul, vault, grafana, n8n, yunxiao, terraform*)
│
└─ Tailscale 直连 ── SSE MCP Server
(billing-* 等内网服务)
0. MCP 管理后台(注册表,2026-08-09 上线)
任何 MCP 服务的凭据/配置/状态,一律查管理后台,禁止依赖 agent 上下文记忆。
- 存储:Consul KV 命名空间
mcp/registry/(内网自持,全节点可达) - CLI:raccoon
/opt/mcp-farm/mcp-registry(或 curl Consul KV)
bash mcp-registry list # 列全部 MCP 服务 mcp-registry creds <svc> # 查某服务的凭据/配置 mcp-registry put <svc> '<json>' # 注册/更新服务 mcp-registry health # 查 coze-mcp 健康 - 规则:新接入 MCP 服务必须
put注册(端口/域名/工具数/凭据位置);拿到新凭据立即入库(如 Agnes key);agent 上下文丢失后从creds <svc>拉取。
1. Consul 服务注册标准
所有 MCP Server 必须在 Consul 中注册服务。注册时遵循以下规范:
Tags
["mcp", "<category>", "<service-name>", "<transport>"]
| Tag | 说明 | 可选值 |
|---|---|---|
mcp |
固定标记,用于识别所有 MCP 服务 | — |
<category> |
分类 | infrastructure, monitoring, devops, billing, ai |
<service-name> |
服务名 | consul, vault, grafana, n8n, yunxiao, terraform |
<transport> |
传输协议 | streamable-http, sse |
Meta
{
"description": "一句话描述",
"protocol": "mcp",
"transport": "streamable-http",
"version": "0.1.0"
}
| 字段 | 必填 | 说明 |
|---|---|---|
description |
✅ | 服务功能描述,会暴露给 AI Agent |
protocol |
✅ | 固定 "mcp" |
transport |
✅ | "streamable-http" 或 "sse" |
version |
✅ | 服务版本 |
健康检查
Streamable HTTP 服务至少配置 TCP 健康检查(端口可达性):
"check": {
"tcp": "<host>:<port>",
"interval": "10s"
}
注册示例
curl -s -X PUT -H "Content-Type: application/json" \
-d '{
"name": "mcp-xxx",
"port": 9199,
"address": "<node-ip>",
"tags": ["mcp", "<category>", "<name>", "streamable-http"],
"meta": {
"description": "XXX MCP Server - 功能描述",
"protocol": "mcp",
"transport": "streamable-http",
"version": "0.1.0"
},
"check": {
"tcp": "<node-ip>:9199",
"interval": "10s"
}
}' \
http://127.0.0.1:8500/v1/agent/service/register
2. Traefik 路由标准(仅 Streamable HTTP)
Streamable HTTP 服务必须通过 Traefik 暴露为 HTTPS。
Tags
在 Consul 注册的 Tags 中追加 Traefik 标签:
"tags": [
"mcp", "<category>", "<name>", "streamable-http",
"traefik.enable=true",
"traefik.http.routers.mcp-<name>.rule=Host(`mcp-<name>.capitaltrain.cn`)",
"traefik.http.routers.mcp-<name>.entrypoints=websecure",
"traefik.http.routers.mcp-<name>.tls.certresolver=cloudflare",
"traefik.http.routers.mcp-<name>.tls.domains[0].main=capitaltrain.cn",
"traefik.http.routers.mcp-<name>.tls.domains[0].sans=*.capitaltrain.cn"
]
域名格式
https://mcp-<name>.capitaltrain.cn/mcp
例外:
- yunxiao-mcp → https://yunxiao.capitaltrain.cn/mcp(特殊命名)
端点路径
| 条件 | 路径 |
|---|---|
| Streamable HTTP | /mcp |
| SSE(无 Traefik) | 根路径 / |
3. 传输协议选择
| 条件 | 推荐协议 |
|---|---|
| 对外暴露(公网) | Streamable HTTP(走 Traefik HTTPS) |
| 内网仅 Tailscale | SSE(直连,省去 Traefik) |
Streamable HTTP 握手流程
Client → Server: POST /mcp (initialize + Mcp-Protocol-Version header)
Server → Client: 200 OK + Mcp-Session-Id header
Client → Server: POST /mcp (tools/list 等, 带 Mcp-Session-Id)
SSE 握手流程
Client → Server: GET / (SSE 长连接)
Server → Client: event: endpoint
data: /messages/?session_id=<id>
Client → Server: POST /messages/?session_id=<id>
(JSON-RPC 请求)
4. opencode.json 配置标准
全局配置位置
~/.config/opencode/opencode.json
Streamable HTTP(最常用)
{
"mcp": {
"<name>": {
"type": "remote",
"url": "https://mcp-<name>.capitaltrain.cn/mcp",
"enabled": true
}
}
}
需要自定义 Header
{
"mcp": {
"yunxiao": {
"type": "remote",
"url": "https://yunxiao.capitaltrain.cn/mcp",
"enabled": true,
"headers": {
"Accept": "application/json, text/event-stream"
}
},
"n8n": {
"type": "remote",
"url": "https://mcp-n8n.capitaltrain.cn/mcp",
"enabled": true,
"headers": {
"Authorization": "Bearer {env:N8N_AUTH_TOKEN}"
}
}
}
}
SSE(内网 Tailscale 直连)
{
"mcp": {
"billing-personal": {
"type": "remote",
"url": "http://<tailscale-ip>:9101",
"enabled": true
}
}
}
Header 值插值语法
opencode 支持两种插值:
| 语法 | 用途 | 示例 |
|---|---|---|
{env:VAR_NAME} |
从环境变量读取 | "Bearer {env:N8N_AUTH_TOKEN}" |
{file:/path} |
从文件读取 | "Bearer {file:~/.token}" |
优先使用 {env:VAR},避免在配置文件中硬编码凭据。
5. 凭据注入(Infisical)
对于需要认证的 MCP Server,token 必须从 Infisical 获取并通过环境变量注入。
Shell 包装函数(推荐)
在 ~/.zshrc 中添加:
# opencode: 只从 Infisical 拉需要的 token
opencode() {
local _token _n8ntoken
_token=$(cat "$HOME/.infisical/token" 2>/dev/null)
[ -n "$_token" ] && _n8ntoken=$(infisical secrets get N8N_AUTH_TOKEN \
--domain https://infisical.git4ta.fun \
--projectId "$INFISICAL_PROJECT_ID" \
--env dev \
--token "$_token" \
--plain 2>/dev/null)
[ -n "$_n8ntoken" ] && export N8N_AUTH_TOKEN="$_n8ntoken"
command opencode "$@"
}
原则:
- 只拉需要的 secret,不灌全部
- 每个新 token 加一行 infisical secrets get 即可
- 真相源始终是 Infisical,不落盘
6. 当前在册 MCP 服务清单
| 服务名 | 节点 | 端口 | 传输 | 路径 | 域名 | 状态 |
|---|---|---|---|---|---|---|
mcp-consul |
nuc | 9190 | streamable-http | /mcp |
mcp-consul.capitaltrain.cn |
✅ |
mcp-vault |
nuc | 9192 | streamable-http | /mcp |
mcp-vault.capitaltrain.cn |
✅ |
mcp-grafana |
nuc | 9193 | streamable-http | / |
mcp-grafana.capitaltrain.cn |
✅ |
mcp-n8n |
xgp(LXC109) | 3100 | streamable-http | /mcp |
mcp-n8n.capitaltrain.cn |
✅ 需 Authorization |
yunxiao-mcp |
nuc | 7568 | streamable-http | /mcp |
yunxiao.capitaltrain.cn |
✅ 需 Accept header |
mcp-terraform* |
nuc | 9191 | — | — | — | ❌ 端口错跑 vault |
mcp-billing-personal |
xgp | 9101 | sse | / |
直连 | ✅ |
mcp-billing-company |
xgp | 9102 | sse | / |
直连 | ✅ |
mcp-billing-seekkeyhk |
xgp | 9103 | sse | / |
直连 | ✅ |
mcp-billing-capitaltrain |
xgp | 9104 | sse | / |
直连 | ✅ |
> * mcp-terraform 在 Consul 中注册了端口 9191,但该端口实际运行的是 vault-mcp-server v0.2.0,未见真正的 terraform MCP 服务。需修复后方可配置。
7. 新增 MCP 服务清单
新增一个 MCP Server 的标准流程:
- [ ] 1. 在目标节点上部署 MCP Server,监听
<port> - [ ] 2. 注册到 Consul(按第 1 节标准)
- [ ] 3. 如对外暴露:添加 Traefik 标签(按第 2 节标准)
-
[ ] 4. 验证连通性:
```bash
# Streamable HTTP
SID=$(curl -s -D - -X POST https://mcp-<name>.capitaltrain.cn/mcp \
-H "Content-Type: application/json" \
-H "Mcp-Protocol-Version: 2025-03-26" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":...}' \
| grep '^mcp-session-id:' | awk '{print $2}')
curl -s -X POST ... -H "Mcp-Session-Id: $SID" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'# SSE
curl -s http://<node>:<port>/
```
- [ ] 5. 配置到 opencode.json(按第 4 节标准)
- [ ] 6. 如需认证:将 token 存入 Infisical,加 shell 包装函数
- [ ] 7. 通知用户重启 opencode 生效