MCP Infrastructure Gateway
README.md
# MCP Infrastructure Gateway
<p align="center">
<img src="https://img.shields.io/badge/license-Apache--2.0-blue.svg" alt="License">
<img src="https://img.shields.io/badge/node-%3E%3D20-339933.svg" alt="Node.js >= 20">
<img src="https://img.shields.io/badge/docker-compose-2496ED.svg" alt="Docker Compose">
<img src="https://img.shields.io/badge/MCP-Server-000000.svg" alt="MCP Server">
</p>
> **An authenticated MCP Gateway for your SSH server fleet and RAG knowledge base.**
> Exposes servers, knowledge search and policy-enforced operations as MCP tools:
> read-only checks run automatically, risky commands require human approval.
远程 Linux MCP Gateway:本机 Harness/Codex 通过 HTTPS 连接 Gateway,Gateway 根据明确的 `target` 通过 SSH 访问博客服务器和中转站,并按策略执行知识库检索、只读检查和审批后的运维操作。
## 特性
- 🔐 **身份与 SSRF 防护**:每人独立 Bearer Token + 来源限流;目标只能使用注册表 ID,请求中传入任意 IP 会被拒绝
- 🛡️ **命令策略引擎**:只读命令自动执行;删除、重启、停服、数据库写入、配置修改等操作必须人工审批
- 🧠 **RAG 知识库**:PostgreSQL 全文检索 + pgvector 向量混合检索(Embedding 可本地 TEI 或 OpenAI 兼容 API)
- 🔑 **Web 管理 SSH 凭据**:私钥/密码加密存储,不在 API 返回、日志或知识库中回显
- 🧩 **MCP 原生**:`list_targets` / `inspect_server` / `run_command` / `search_knowledge` 等 18 个工具,附技能手册与知识库检索
- 📦 **安全部署**:docker compose 一键启动,Caddy TLS、read-only 容器、非 root 运行、最低权限 SSH 目标用户
## 结构
```mermaid
flowchart LR
subgraph Client[Harness / Codex / MCP client]
H[HTTPS + Bearer Token]
end
subgraph Edge[Caddy - TLS termination]
C[HTTPS 443]
end
subgraph GW[Gateway container - read-only]
M[MCP Server<br>18 tools]
P[Policy & approval engine]
S[SSH manager<br>web-managed credentials]
K[RAG knowledge search<br>pgvector hybrid]
end
subgraph Targets[SSH targets]
T1[blog-prod]
T2[relay-prod]
end
DB[(PostgreSQL<br>+ pgvector)]
H -- HTTPS/MCP --> C -- private network --> M
M --> P --> S -- SSH --> T1
S -- SSH --> T2
K --> DB
```
## 安全边界
- Gateway 只监听容器内部 HTTP;公网 TLS 由 Caddy 终止。
- MCP 请求使用每人独立的 Bearer Token。
- 认证失败按来源地址限流;正式部署仍建议叠加 VPN、Cloudflare Access 或防火墙白名单。
- SSH 私钥只读挂载到 Gateway 的 `/run/secrets`,不进入 Git、知识库或 MCP 返回结果。
- 目标只能使用 `targets.yaml` 中的 ID,不能从请求中传入任意主机地址。
- 禁止 root、`sudo`、shell 链接/替换/重定向和全局高危命令。
- 只读命令自动执行;配置、部署、重启等命中 approval allowlist 的操作必须先审批。
- 用户只能访问自己的目标服务器和项目知识。
- PostgreSQL 中保存审批状态和审计日志;日志不保存密钥。
## Linux 部署
以下命令在远程 Gateway Linux 主机执行:
```bash
cp .env.example .env
install -d -m 700 secrets
cp config/targets.example.yaml config/targets.yaml
cp config/auth.example.yaml config/auth.yaml
chmod 600 .env config/*.yaml
```
生成用户 Token 的哈希,不要把明文 Token 提交到文件:
```bash
node scripts/hash-token.mjs "生成一段随机长Token"
```
把输出的 `sha256:...` 写入 `config/auth.yaml` 的 `token_hash`。明文 Token 只放在本机 Harness 的环境变量中。
将 SSH 私钥和已核验的主机指纹放入 `secrets/`:
```bash
install -m 600 /secure/source/blog_ssh_key secrets/blog_ssh_key
install -m 600 /secure/source/relay_ssh_key secrets/relay_ssh_key
install -m 600 /secure/source/known_hosts secrets/known_hosts
```
目标服务器应使用独立的非 root 用户,并把 Gateway 的公钥加入该用户的 `~/.ssh/authorized_keys`。确认 `known_hosts` 后再启动服务。
配置 `.env`:
```dotenv
POSTGRES_PASSWORD=long-random-database-password
MCP_DOMAIN=mcp.example.com
DATABASE_URL=postgres://mcp_gateway:long-random-database-password@db:5432/mcp_gateway
```
启动:
```bash
docker compose up -d --build
docker compose --profile index run --rm indexer
curl -fsS https://mcp.example.com/healthz
```
## 本机 Harness/Codex 配置
```bash
export MCP_GATEWAY_TOKEN='本机保存的明文Token'
codex mcp add infra-gateway \
--url https://mcp.example.com/mcp \
--bearer-token-env-var MCP_GATEWAY_TOKEN
```
Windows PowerShell:
```powershell
$env:MCP_GATEWAY_TOKEN = "本机保存的明文Token"
codex mcp add infra-gateway `
--url https://mcp.example.com/mcp `
--bearer-token-env-var MCP_GATEWAY_TOKEN
```
## 知识库与 RAG
`knowledge/` 中的 Markdown、YAML、JSON 和文本文件由 `indexer` 切块写入 PostgreSQL。默认使用 PostgreSQL 全文检索;配置 `EMBEDDING_BASE_URL`、`EMBEDDING_API_KEY` 和 `EMBEDDING_MODEL` 后,索引器和查询会额外使用 pgvector 做混合检索。
硬性限制单独存放在 `config/rules.yaml`,每次由 `get_constraints` 读取,不依赖向量召回。服务器最新日志、状态和端口通过 SSH 工具实时查询,不放入 RAG。
## MCP 工具
```text
list_targets()
list_projects()
get_constraints(scope?)
search_knowledge(project, query, limit?)
read_document(project, path)
inspect_server(target, check)
read_logs(target, service, lines?)
run_command(target, command, approval_id?)
list_pending_approvals()
decide_approval(approval_id, decision)
```
## 生产前检查
- 将 Gateway 放在 Tailscale/WireGuard 或防火墙之后,SSH 只允许 Gateway 固定地址。
- 将 `auth.yaml`、`targets.yaml` 和 `secrets/` 的权限限制为部署管理员和容器所需用户。
- 为每个人创建独立 Token,人员离开时撤销并重新部署配置。
- 将 PostgreSQL 和 Caddy 数据卷纳入备份;不要备份明文 SSH 私钥到普通备份桶。
- 为审批和审计日志设置保留期限,并监控 Gateway、SSH 和数据库异常。
- 在 staging 目标上验证命令规则后,再添加生产目标。
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues