关于 toolmesh
ToolMesh 是供自行托管的网关,用于连接 AI Agent 与 REST API 及现有 MCP 服务。通过声明式 DADL 文件定义 REST 工具,并以授权、凭据处理、策略和审计记录管理调用。
主要功能
- 01用 YAML DADL 将 REST API 描述为工具
- 02代理现有 MCP 服务
- 03在执行时注入凭据
- 04按用户、角色、计划或公司授权调用
- 05用 JavaScript 策略过滤输入和输出
- 06将工具调用记录到结构化日志或 SQLite
适用场景
- 01无需构建包装服务即可开放 REST API 操作
- 02按角色或计划限制 Agent 工具访问
- 03避免凭据进入提示词和客户端配置
- 04审计不同系统中的工具活动
MCP 相关
ToolMesh 作为 MCP 网关,公开 DADL 定义的 REST API 工具并代理现有 MCP 服务。MCP 客户端连接其端点;远程访问可使用带 PKCE 的 OAuth 2.1。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://{host}:8123/mcpclaude mcp add --transport http dunkelcloud-toolmesh https://{host}:8123/mcp{"mcpServers":{"dunkelcloud-toolmesh":{"type":"http","url":"https://{host}:8123/mcp"}}}在 Cursor 中打开{"servers":{"dunkelcloud-toolmesh":{"type":"http","url":"https://{host}:8123/mcp"}}}在 VS Code 中打开{"mcpServers":{"dunkelcloud-toolmesh":{"type":"http","url":"https://{host}:8123/mcp"}}}{"mcpServers":{"dunkelcloud-toolmesh":{"serverUrl":"https://{host}:8123/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
ToolMesh — 让 AI Agent 安全地接入真实系统。
AI Agent 与企业系统之间缺少的控制层。ToolMesh 将不受控的 AI 工具调用转变为受管控、可审计的流程,并在几分钟内(而不是几个月)连接任意 REST API 或 MCP 服务。
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,只需向大模型提问。Claude、GPT、Gemini——任何了解 DADL 规范的模型,都能在几秒内生成可用的 .dadl 文件。描述你的需求,将文件放入 config/dadl/,就完成了。
“为 GitHub API 创建一个 DADL——列出仓库、打开议题并创建拉取请求。”
只需 10 秒。任何了解该格式的大模型都能完成。
与只转发工具调用的 MCP 网关不同,ToolMesh 还提供了生产环境部署真正需要的功能:
- 凭证安全 — 在执行时注入机密信息,绝不放入提示词或大模型客户端配置中
- 授权 — 默认启用:按用户、角色、套餐或公司控制谁可以调用哪些工具(内置 OpenFGA)
- 输入与输出管控 — JS 策略可阻止机密数据并筛选响应
- 审计跟踪 — 通过结构化日志或可查询的 SQLite 记录每次工具调用
六大支柱
| 支柱 | 功能 | 支持方式 |
|---|---|---|
| 任意后端 | 30 行 DADL 即可取代整个 MCP 服务。也可代理现有 MCP 服务。 | Go MCP SDK + DADL(.dadl 文件) |
| 代码模式 | 同时使用 15 个 MCP 服务?没有 ToolMesh 就办不到。代码模式可将 50,000+ 个 token 减少到约 1,000 个。 | 通过 AST 解析的工具调用 |
| 凭证存储 | 在执行时注入机密信息——绝不放入提示词或大模型客户端配置中 | 通过 Executor 流水线按请求注入 |
| OpenFGA | 默认启用细粒度授权,无需安装任何组件(用户 → 套餐 → 工具)。示例:免费用户仅可读取,专业版用户可使用全部功能。 | OpenFGA,可嵌入或外部部署 |
| 管控 | 在执行前阻止机密数据,在响应中编辑个人身份信息 | goja |
| 审计 | 记录并查询每次工具调用——用 SQL 回答“那个 Agent 做了什么?” | slog / SQLite |
试用演示
想先试用 ToolMesh 再安装?连接到我们的公开演示实例——无需 Docker、配置或 API 密钥:
demo.toolmesh.io — 通过 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
# IMPORTANT: Set a password — without it, all requests are rejected:
# TOOLMESH_AUTH_PASSWORD=my-secret-password
# Or set an API key for programmatic access:
# TOOLMESH_API_KEY=my-api-key
# Optional: local overrides (build locally, external OpenFGA, HTTPS proxy, ...)
# cp docker-compose.override.yml.example docker-compose.override.yml
# # then edit docker-compose.override.yml — picked up automatically by Docker Compose
# Start (authorization is on: the password/API key above gets every tool;
# without a password or API key every request is rejected)
docker compose up -d
# Verify it's running (default port: 8123)
curl http://localhost:8123/health
# MCP endpoint: http://localhost:8123/mcp
# Note: Most MCP clients require HTTPS — see TLS section below
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 状态(令牌、授权码、客户端)都持久化在 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 中定义 API 密钥。每个条目使用密钥的 SHA-256 值来标识密钥:
keys:
- key_sha256: "<SHA-256 of the key, 64 hex characters>"
user_id: claude-code-user
company_id: dunkelcloud
plan: pro
roles: [tool-executor]
生成密钥及其 key_sha256:
KEY="tm_$(openssl rand -hex 32)"
printf '%s' "$KEY" | sha256sum | cut -d' ' -f1
每个密钥都对应一个独立的用户身份,拥有自己的套餐和角色,这些信息会传递给授权流程。
对于包含 bcrypt key_hash 的条目(较早版本写入的文件中有此字段),无需任何更改即可继续使用。在启动后首次使用该密钥之前,每次遇到其他方式都无法识别的持有者凭据时,都会为这类条目执行一次 bcrypt 比较;key_sha256 则会直接查找,适用于随机生成的密钥。详情及两种形式的区别请参阅 docs/configuration.md。
对于单密钥配置,TOOLMESH_API_KEY 仍可用作备用方案。身份由相同的 TOOLMESH_AUTH_USER、TOOLMESH_AUTH_PLAN 和 TOOLMESH_AUTH_ROLES 变量控制。
未经身份验证的请求
对 /mcp 的请求如果没有有效凭据,服务器会返回 401,并附带包含 resource_metadata 的 WWW-Authenticate: Bearer 挑战,符合 MCP 授权规范的要求。MCP 客户端会在收到此状态时启动 OAuth 流程,或刷新已过期的令牌。此类请求会以 INFO 级别记录,并计入 toolmesh_logins_total{method="anonymous"}。请参阅 docs/configuration.md。
DCR 速率限制
动态客户端注册每个 IP 每小时最多允许 5 次,以防止滥用。
登录限流
密码登录失败次数会按账户和客户端地址分别限制:默认情况下,15 分钟内同一账户来自同一地址的失败次数上限为 5 次,同一账户来自所有地址的失败次数上限为 20 次,同一地址对所有账户的失败次数上限为 50 次。超过限制后,登录会返回 429,直到限流窗口结束。每次登录失败都会以 WARN 级别记录,并计入 toolmesh_logins_total{result="failure"}。已签发的令牌和 API 密钥不受锁定影响。有关相关变量以及按地址限制所需的反向代理配置,请参阅 docs/configuration.md。
整个进程同时执行的 bcrypt 比较次数设有上限(TOOLMESH_BCRYPT_MAX_CONCURRENT,默认值:可用 CPU 数量的一半),以免密码登录占用 CPU,影响其他所有任务。请参阅 docs/configuration.md。
授权
每次工具调用都会经过检查,工具列表也只会向每个调用方显示其有权调用的工具。无需进行任何设置:ToolMesh 会在自身进程中运行 OpenFGA,并将数据保存在 data/authz.db 中。
TOOLMESH_AUTHZ_MODE 用于选择引擎:
| 模式 | 行为 |
|---|---|
embedded(默认) | 在 ToolMesh 内部执行检查。授权来自预设或 config/authz.yaml。 |
external | 将检查发送到由你运行的 OpenFGA 服务(OPENFGA_API_URL、OPENFGA_STORE_ID)。ToolMesh 不会向其写入数据。 |
disabled | 不执行检查。每次启动时都会报告,并记录在审计跟踪中。 |
授权规则引用 users.yaml、apikeys.yaml 中的用户、角色、方案和公司,或单个密码/API 密钥。没有授权规则文件时,将应用预设:
| 预设 | 谁可以调用哪些工具 |
|---|---|
single-user | 所有者(TOOLMESH_AUTH_USER)和角色 admin:所有工具。没有 users.yaml/apikeys.yaml 时的默认值。 |
team | 与 single-user 相同,此外方案 pro:所有工具,方案 free:所有 read 工具。有 users.yaml 或 apikeys.yaml 时的默认值。 |
open | 每个经过身份验证的调用方:所有工具 |
如需更精细的控制,请将 config/authz.yaml.example 复制到 config/authz.yaml;授权规则可指定所有工具、后端、单个工具或 DADL 访问类别(read、write 等);拒绝规则会阻止其中任何一项,且优先级高于所有授权规则。更改会在数秒内生效:
grants:
- plan: pro
backends: [github, deepl]
- plan: free
access: [read]
- role: support
tools: [zammad_list_tickets]
denies:
- plan: pro
tools: [stripe_create_refund]
从不包含授权功能的版本升级而来的安装,会向每个经过身份验证的调用方开放所有工具(预设为 open),并在每次启动时提示这一点,直到你选择某个预设或编写授权规则。OPENFGA_MODE 已弃用:restrict 映射为 external,bypass 映射为 embedded。请参阅 docs/configuration.md。
启动时的安全状况
ToolMesh 默认安全:它不会内置任何会悄然放宽控制的默认设置。启动时,它会记录一条安全状况摘要,列出所有仍处于宽松状态的控制(缺少身份验证凭据、禁用授权或向所有人开放、开放 CORS、调试工具、关闭登录限制),并说明如何加强这些控制。在默认的生产安全配置下,这些信息会以 WARN 级别记录;在本地开发机器上设置 TOOLMESH_DEV=true,则会以 INFO 级别报告同样的信息,且仅报告一次,避免警告变成背景噪声。TOOLMESH_DEV 只会更改此摘要的日志级别,本身绝不会放宽任何设置。
配置
所有环境变量请参阅 docs/configuration.md。
超时调整
| 变量 | 默认值 | 描述 |
|---|---|---|
TOOLMESH_MCP_TIMEOUT | 120 | 调用下游 MCP 服务的 HTTP 客户端超时时间(秒) |
TOOLMESH_EXEC_TIMEOUT | 120 | 工具执行超时时间(秒)——后端调用的上下文截止时间 |
对于需要更多时间的后端(例如基于浏览器的网页抓取工具),请调高这些值:
TOOLMESH_MCP_TIMEOUT=180
TOOLMESH_EXEC_TIMEOUT=180
日志记录
ToolMesh 使用 slog 进行结构化日志记录。默认级别为 info。诊断问题时,可设置 LOG_LEVEL=debug 来跟踪完整的 MCP 请求/响应流程;但请注意,调试日志包含完整的请求 URL 和负载,因此对于查询字符串中的 API 密钥,凭据会出现在日志中。生产环境中请勿启用 debug。各后端的调试文件、日志格式和所有日志变量均记录在 docs/configuration.md 中。
指标(Prometheus)
ToolMesh 在单独的监听器上暴露 Prometheus 指标(默认主机端口为 9090)——按方法和结果统计的登录次数、按后端和结果统计的工具调用速率,以及采用 REST 优化分桶的延迟直方图。该端点未经过身份验证,因此 Compose 文件默认将主机端口绑定到 127.0.0.1(本地和同一 Docker 网络中的 Prometheus 均可访问,公共网络接口无法访问)。只有在从其他主机抓取指标且已自行配置端口防火墙时,才设置 TOOLMESH_METRICS_HOST=0.0.0.0。
在 .env 中通过 TOOLMESH_METRICS_PORT、TOOLMESH_METRICS_ENABLED 和 TOOLMESH_METRICS_LABEL_TOOL 进行配置。完整的架构、PromQL 查询示例和抓取配置示例,请参阅 docs/metrics.md。
调试工具(选择启用)
在 .env 中设置 TOOLMESH_DEBUG_TOOLS=true,即可暴露两个诊断 MCP 工具——debug_echo(返回所提供负载的大小和 SHA-256,不使用后端)和 debug_generate(生成 N 字节的可打印字符串)。可用它们探测调用方大模型与 ToolMesh 之间的传输层大小限制,或验证往返字节完整性。默认关闭;用于开发和事故排查,不适用于生产环境。
架构
完整的架构文档请参阅 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)。凭据由执行器在运行时通过 CredentialStore 注入——大模型永远无法看到 API 密钥。
REST 代理模式(DADL)
当 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 issue?只需这样做:
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。创建 .dadl 文件最快的方法,是询问任何了解此格式的大模型。
代码模式
将 15 个 MCP 服务连接到单个 AI Agent?没有 ToolMesh,这根本行不通——上下文窗口会被填满,客户端也会不堪重负。代码模式让这一切成为可能。
ToolMesh 不再暴露数百个独立工具定义(超过 50,000 个 token),而是暴露两个元工具:discover_tools 和 execute_code。大模型会获取精简的 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() 注册进行扩展:
| 组件 | 内置 | 配置 |
|---|---|---|
| 凭据存储 | embedded | CREDENTIAL_STORE=<name> |
| 工具后端 | mcp、rest(DADL)、echo | config/backends.yaml |
| Gate 评估器 | goja | GATE_EVALUATORS=<list> |
企业扩展(InfisicalStore、VaultStore、Compliance-LLM 等)已列入计划,将通过 Go 构建标签引入:go build -tags enterprise ./cmd/toolmesh。
详情请参阅 docs/architecture.md。
背后团队
ToolMesh 由 Axel Dunkel 在 Dunkel Cloud GmbH 构建并维护。这是一家德国公司,致力于构建将 AI Agent 连接到实际系统的基础设施。ToolMesh 和 DADL 源自我们多年来为企业运行的生产级云和边缘基础设施,因此这并非一个由匿名账号维护的业余项目:它运行在我们自己的技术栈中,回复 [email protected] 的也是编写代码的同一批人。
配套的 DADL registry 目前提供 27 个社区 API 描述,涵盖约 3,300 个生成的工具——从包含 4 个工具的 Hacker News 阅读器,到覆盖 NetBox DCIM/IPAM 的 608 个工具;每项都显示 API 覆盖率百分比,让你清楚了解其完整程度。
- 🌐 网站:toolmesh.io
- 📖 DADL 规范和注册表:dadl.ai
- 🐛 安全联系邮箱:[email protected](参见 SECURITY.md)
参与贡献
请参阅 CONTRIBUTING.md。
许可证
Apache 2.0 — 版权所有 2025–2026 Dunkel Cloud GmbH
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。