DunkelCloud/ToolMesh

GitHub: DunkelCloud/ToolMesh

一个自托管的 MCP 网关,为 AI Agent 提供凭证注入、细粒度授权、输入输出门控和审计日志,并通过声明式 DADL 格式将任意 REST API 直接暴露为 MCP 工具。

Stars: 2 | Forks: 0

# ToolMesh — 让 AI Agent 安全地接触真实系统。 [![Go](https://img.shields.io/badge/Go-1.25+-00ADD8?style=flat&logo=go)](https://go.dev) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/05/8889233709112235.svg)](https://github.com/DunkelCloud/ToolMesh/actions/workflows/ci.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/DunkelCloud/ToolMesh)](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配置, 凭证注入, 审计日志, 开源, 搜索引擎查询, 数据防泄露, 日志审计, 程序破解, 策略引擎, 网络安全, 网络安全挑战, 自定义请求头, 自托管, 访问控制, 请求拦截, 输入输出控制, 隐私保护