DunkelCloud/ToolMesh
GitHub: DunkelCloud/ToolMesh
一个自托管的 MCP 网关,为 AI Agent 提供凭证注入、细粒度授权、输入输出门控和审计日志,并通过声明式 DADL 格式将任意 REST API 直接暴露为 MCP 工具。
Stars: 2 | Forks: 0
# ToolMesh — 让 AI Agent 安全地接触真实系统。
[](https://go.dev)
[](LICENSE)
[](https://github.com/DunkelCloud/ToolMesh/actions/workflows/ci.yml)
[](https://goreportcard.com/report/github.com/DunkelCloud/ToolMesh)
## 30 行 YAML。无需构建服务器。
在实际使用中,MCP 服务器仅暴露了它们所封装的 REST API 的一小部分——你会很快遇到覆盖不到的盲区。ToolMesh 允许你使用 `.dadl` 文件来替代这层包装——这是一种声明式的 YAML 格,可以将任何 REST API 描述为 MCP 工具。无需构建、部署或维护包装服务器。
```
Current: Claude → ToolMesh → MCP Server → REST API
With DADL: Claude → ToolMesh → REST API (via .dadl file)
```
你不需要手动编写 YAML。你可以求助于 LLM。Claude、GPT、Gemini——任何了解 DADL 规范的模型都能在几秒钟内生成一个可用的 `.dadl` 文件。描述你的需求,将文件放入 `config/dadl/` 目录中即可搞定。
只需 10 秒。适用于任何支持该格式的 LLM。
与仅仅透传工具调用的 MCP 网关不同,ToolMesh 增加了生产环境部署真正需要的功能:
- **凭证安全** —— 密钥在执行时注入,绝不出现在提示或 LLM 客户端配置中
- **授权控制** —— 细粒度的 user → plan → tool 控制 (OpenFGA)
- **输入与输出门控** —— JS 策略可阻止机密数据并过滤响应
- **审计追踪** —— 通过结构化日志或可查询的 SQLite 记录每一次工具调用
## 六大支柱
| 支柱 | 作用 | 支持技术 |
|--------|-------------|-----------|
| **任意后端** | 30 行 DADL 即可替代一整个 MCP 服务器。同时也支持代理现有的 MCP 服务器。 | Go MCP SDK + DADL (.dadl 文件) |
| **代码模式** | 同时连接 15 个 MCP 服务器?没有 ToolMesh 根本不可能。代码模式可将 50,000+ token 削减至约 1,000 个。 | AST 解析的工具调用 |
| **凭证存储** | 密钥在执行时注入——绝不出现在提示或 LLM 客户端配置中 | 通过 Executor 管道实现按请求注入 |
| **OpenFGA** | 细粒度授权控制 (user → plan → tool)。例如:免费用户仅拥有只读权限,专业版用户拥有所有权限。 | OpenFGA |
| **门控** | 在执行前阻止机密数据,在响应中脱敏 PII (个人身份信息) | goja |
| **审计** | 记录每一次工具调用且支持查询——使用 SQL 回答“那个 agent 做了什么?” | slog / SQLite |
## 体验演示
想在安装前试用 ToolMesh 吗?连接到我们的公开演示实例——无需 Docker、无需配置、无需 API 密钥:
**[demo.toolmesh.io](https://toolmesh.io/demo)** —— 通过 ToolMesh 提供的 Hacker News API。支持 Claude Desktop、Claude Code 和 ChatGPT。登录账号:`dadl` / `toolmesh`。
## 快速开始
```
# Clone
git clone https://github.com/DunkelCloud/ToolMesh.git
cd ToolMesh
# Configure
cp .env.example .env
# 重要提示:设置密码 — 未设置时所有请求将被拒绝:
# TOOLMESH_AUTH_PASSWORD=my-secret-password
# 或者设置 API key 以进行 programmatic access:
# TOOLMESH_API_KEY=my-api-key
# 可选:本地覆盖(本地构建,启用 OpenFGA,HTTPS proxy,...)
# cp docker-compose.override.yml.example docker-compose.override.yml
# # 然后编辑 docker-compose.override.yml — Docker Compose 会自动拾取
# 启动(默认在 bypass 模式下运行 — 无需 authz)
docker compose up -d
# 验证是否正在运行(默认端口:8123)
curl http://localhost:8123/health
# MCP endpoint: http://localhost:8123/mcp
# 注意:大多数 MCP 客户端要求 HTTPS — 参见下方的 TLS 部分
```
### TLS (很重要)
ToolMesh 本身提供的是纯 HTTP 服务。**大多数 MCP 客户端——包括 Claude Desktop——要求使用 HTTPS**,并且会拒绝 `http://` URL。你需要在 ToolMesh 前面配置一个 TLS 终止反向代理:
| 选项 | 适用场景 |
|--------|-------------|
| **Caddy** | 拥有公共域名的自托管环境——自动提供 Let's Encrypt 证书 |
| **Cloudflare Tunnel** | 无需开放端口,零配置 TLS |
| **nginx / Traefik** | 已在你现有技术栈中的方案 |
仅在**本地开发**时,你可以通过手动编辑 `claude_desktop_config.json` 来绕过 TLS (其图形界面强制要求使用 `https://`)。
### 连接到 Claude Desktop
将以下内容添加到你的 Claude Desktop MCP 配置中:
```
{
"mcpServers": {
"toolmesh": {
"url": "https://toolmesh.example.com/mcp"
}
}
}
```
适用于没有 TLS 代理的本地开发环境:
```
{
"mcpServers": {
"toolmesh": {
"url": "http://localhost:8123/mcp"
}
}
}
```
### 连接到 Claude.ai (自定义连接器)
ToolMesh 支持使用带有 PKCE S256 的 OAuth 2.1 进行远程访问。在 `config/users.yaml` 中配置用户,并使用公共 HTTPS URL 作为 MCP 端点。
## 身份验证
ToolMesh 支持两种可以独立或组合使用的身份验证方法。所有的 OAuth 状态(token、授权码、客户端)都持久化在 Redis 中,并且在服务器重启后依然保留。
### OAuth 2.1 (交互式登录)
在 `config/users.yaml` 中定义使用 bcrypt 哈希密码的用户:
```
users:
- username: admin
password_hash: "$2a$10$..."
company: dunkelcloud
plan: pro
roles: [admin]
```
使用任何支持 bcrypt 的工具生成密码哈希:
```
htpasswd -nbBC 10 "" "my-password" | cut -d: -f2
```
对于单用户设置,`TOOLMESH_AUTH_PASSWORD` 仍可作为备选方案。可通过 `TOOLMESH_AUTH_USER`、`TOOLMESH_AUTH_PLAN` 和 `TOOLMESH_AUTH_ROLES` 配置身份(默认值:`owner`、`pro`、`admin`)。
### API 密钥 (编程访问)
在 `config/apikeys.yaml` 中定义经过 bcrypt 哈希处理的 API 密钥:
```
keys:
- key_hash: "$2a$10$..."
user_id: claude-code-user
company_id: dunkelcloud
plan: pro
roles: [tool-executor]
```
每个密钥都映射到一个具有独立计划和角色的用户身份,这些信息将贯穿到 OpenFGA 的授权流程中。
对于单密钥设置,`TOOLMESH_API_KEY` 仍可作为备选方案。相同的 `TOOLMESH_AUTH_USER`、`TOOLMESH_AUTH_PLAN` 和 `TOOLMESH_AUTH_ROLES` 变量用于控制该身份。
### DCR 速率限制
动态客户端注册 (Dynamic Client Registration) 的速率限制为每个 IP 每小时 5 次注册,以防止滥用。
## 授权模式
`OPENFGA_MODE` 用于控制是否执行 OpenFGA 授权:
| 模式 | 行为 |
|------|----------|
| `bypass` (默认) | 允许所有工具调用,不进行授权检查 |
| `restrict` | OpenFGA 强制执行 user → plan → tool 授权 (需要配置 `OPENFGA_STORE_ID`) |
建议从 `bypass` 模式开始以快速运行,然后在引导配置好 OpenFGA 后切换到 `restrict` 模式。
## 配置
有关所有环境变量的说明,请参见 [docs/configuration.md](docs/configuration.md)。
### 超时调优
| 变量 | 默认值 | 描述 |
|----------|---------|-------------|
| `TOOLMESH_MCP_TIMEOUT` | `120` | 调用下游 MCP 服务器的 HTTP 客户端超时时间(秒) |
| `TOOLMESH_EXEC_TIMEOUT` | `120` | 工具执行超时时间(秒)——后端调用的上下文截止时间 |
如果后端需要更多处理时间(例如基于浏览器的网页抓取器),请增加这些值:
```
TOOLMESH_MCP_TIMEOUT=180
TOOLMESH_EXEC_TIMEOUT=180
```
### 日志记录
ToolMesh 使用 `slog` 进行结构化日志记录。默认级别为 `debug`,以便开箱即用地提供完整的 MCP 可追踪性——**在生产环境中请务必设置 `LOG_LEVEL=info` 或更高级别**,因为 debug 级别的日志会包含完整的请求/响应载荷。针对每个后端的 debug 文件、日志格式以及所有的日志变量都记录在 [docs/configuration.md](docs/configuration.md#logging) 中。
### 指标 (Prometheus)
ToolMesh 在一个独立的监听器上暴露 Prometheus 指标(默认主机端口 9090)——包括按方法和结果统计的登录次数、按后端和执行结果统计的工具调用速率,以及一个专为 REST 调优的延迟直方图。该端点无需身份验证,因此请将其绑定到私有网络接口,或者仅将其暴露给你的 Prometheus 实例。
可通过 `.env` 中的 `TOOLMESH_METRICS_PORT`、`TOOLMESH_METRICS_ENABLED` 和 `TOOLMESH_METRICS_LABEL_TOOL` 进行配置。有关完整的 schema、示例 PromQL 查询以及示例抓取配置,请参见 [docs/metrics.md](docs/metrics.md)。
### 调试工具 (选启用)
在 `.env` 中设置 `TOOLMESH_DEBUG_TOOLS=true` 可暴露两个诊断性的 MCP 工具——`debug_echo`(返回所提供载荷的大小和 SHA-256 哈希值,无需后端)和 `debug_generate`(生成一个包含 N 个字节的可打印字符串)。使用它们来探测调用 LLM 与 ToolMesh 之间传输层的字节大小限制,或用于验证往返字节的完整性。默认关闭;仅用于开发和事件排查,不适用于生产环境。
## 架构
有关完整的架构文档,请参见 [docs/architecture.md](docs/architecture.md)。
```
┌─────────────────────────────────┐
│ ToolMesh │
│ │
│ Redis · OpenFGA · Audit │
│ Credential Store · JS Gate │
│ │
AI Agent ──MCP──────────▶ │ AuthZ ▸ Creds ▸ Gate ▸ Exec │
│ │
└──┬──────┬───────┬───────┬───────┘
│ │ │ │
MCP Client .dadl .dadl .dadl
│ │ │ │
▼ ▼ ▼ ▼
MCP Stripe GitHub Vikunja
Server API API API
```
## 添加外部 MCP 服务器
创建或编辑 `config/backends.yaml`:
```
backends:
- name: memorizer
transport: http
url: "https://memorizer.example.com/mcp"
api_key_env: "MEMORIZER_API_KEY"
```
将凭证设置为环境变量:
```
CREDENTIAL_MEMORIZER_API_KEY=sk-mem-xxxxx
```
每个后端的工具在暴露时都会带有一个前缀(例如 `memorizer_retrieve_knowledge`)。凭证由 Executor 在运行时通过 CredentialStore 注入——LLM 永远不会看到 API 密钥。
## REST 代理模式 ([DADL](https://dadl.ai))
当 MCP 服务器没有暴露你需要的端点时,只需在 `.dadl` 文件中描述它,ToolMesh 就会直接调用 REST API——无需包装服务器。这两种模式可并行运行。
向 `config/backends.yaml` 添加一个 REST 后端:
```
backends:
- name: vikunja
transport: rest
dadl: /app/dadl/vikunja.dadl
url: "https://vikunja.example.com/api/v1"
```
对于具有私有 IP 或自签名证书的内部服务:
```
backends:
- name: internal-api
transport: rest
dadl: internal.dadl
url: "https://192.168.1.50:8443/api"
allow_private_url: true # allow private/loopback addresses (default: true)
tls_skip_verify: true # accept self-signed certificates (default: false)
```
想让 Claude 列出 GitHub issues?只需这样做:
```
tools:
list_issues:
method: GET
path: /repos/{owner}/{repo}/issues
description: "List issues for a repository"
params:
owner: { type: string, in: path, required: true }
repo: { type: string, in: path, required: true }
state: { type: string, in: query }
```
ToolMesh 负责处理身份验证、分页、重试和错误映射。DADL 支持 bearer token、OAuth2、会话认证、API 密钥、自动分页、带退避的重试、响应转换、组合工具等功能。
有关完整的规范、示例和社区注册表,请参见 [dadl.ai](https://dadl.ai)。创建 `.dadl` 文件最快的方法是让任何了解该格式的 LLM 来生成。
## 代码模式
将 15 个 MCP 服务器连接到单个 AI agent?如果没有 ToolMesh,这根本行不通——上下文窗口会被塞满,客户端也会崩溃。代码模式让这成为可能。
ToolMesh 不再暴露成百上千个单独的工具定义(50,000+ token),而是暴露两个元工具:`discover_tools` 和 `execute_code`。LLM 会获取简洁的 TypeScript 接口(约 1,000 token)并针对它们编写 JavaScript:
```
const repos = await toolmesh.github_list_repos({ sort: "updated" });
const issues = await toolmesh.github_list_issues({
owner: repos[0].owner.login,
repo: repos[0].name,
state: "open"
});
```
在单次往返中实现多次 API 调用。ToolMesh 负责解析代码、提取工具调用,并通过完整的执行管道对它们进行路由。
## 扩展模型
ToolMesh 采用基于注册表的扩展模型,其灵感来源于 Go 的 `database/sql` 驱动模式。通过 `init()` 注册,共有三种组件类型是可扩展的:
| 组件 | 内置 | 配置 |
|-----------|----------|--------|
| Credential Store | `embedded` | `CREDENTIAL_STORE=` |
| Tool Backend | `mcp`, `rest` (DADL), `echo` | `config/backends.yaml` |
| Gate Evaluator | `goja` | `GATE_EVALUATORS=
- ` |
企业级扩展(InfisicalStore、VaultStore、Compliance-LLM 等)已在计划中,并将通过 Go build tags 引入:`go build -tags enterprise ./cmd/toolmesh`。
详情请参见 [docs/architecture.md](docs/architecture.md#extension-model)。
## 贡献
请参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
## 许可证
Apache 2.0 —— 版权所有 2025–2026 [Dunkel Cloud GmbH](https://dunkel.cloud)
标签:AI代理安全, API代理, API管理, API网关, CISA项目, DADL, EVTX分析, Go语言, LLM工具, MCP网关, OpenFGA, REST API转换, SQLite, Streamlit, ToolMesh, YAML配置, 凭证注入, 审计日志, 开源, 搜索引擎查询, 数据防泄露, 日志审计, 程序破解, 策略引擎, 网络安全, 网络安全挑战, 自定义请求头, 自托管, 访问控制, 请求拦截, 输入输出控制, 隐私保护