mcpField
T
toolmesh

toolmesh

远程服务
github.com/DunkelCloud开发工具64 天前更新
代码仓库

关于 toolmesh

ToolMesh 是供自行托管的网关,用于连接 AI Agent 与 REST API 及现有 MCP 服务。通过声明式 DADL 文件定义 REST 工具,并以授权、凭据处理、策略和审计记录管理调用。

主要功能

  1. 01用 YAML DADL 将 REST API 描述为工具
  2. 02代理现有 MCP 服务
  3. 03在执行时注入凭据
  4. 04按用户、角色、计划或公司授权调用
  5. 05用 JavaScript 策略过滤输入和输出
  6. 06将工具调用记录到结构化日志或 SQLite

适用场景

  1. 01无需构建包装服务即可开放 REST API 操作
  2. 02按角色或计划限制 Agent 工具访问
  3. 03避免凭据进入提示词和客户端配置
  4. 04审计不同系统中的工具活动

MCP 相关

ToolMesh 作为 MCP 网关,公开 DADL 定义的 REST API 工具并代理现有 MCP 服务。MCP 客户端连接其端点;远程访问可使用带 PKCE 的 OAuth 2.1。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://{host}:8123/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

ToolMesh — 让 AI Agent 安全地接入真实系统。

AI Agent 与企业系统之间缺少的控制层。ToolMesh 将不受控的 AI 工具调用转变为受管控、可审计的流程,并在几分钟内(而不是几个月)连接任意 REST API 或 MCP 服务。

Go License CI Go Report Card

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_TIMEOUT120调用下游 MCP 服务的 HTTP 客户端超时时间(秒)
TOOLMESH_EXEC_TIMEOUT120工具执行超时时间(秒)——后端调用的上下文截止时间

对于需要更多时间的后端(例如基于浏览器的网页抓取工具),请调高这些值:

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() 注册进行扩展:

组件内置配置
凭据存储embeddedCREDENTIAL_STORE=<name>
工具后端mcp、rest(DADL)、echoconfig/backends.yaml
Gate 评估器gojaGATE_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 覆盖率百分比,让你清楚了解其完整程度。

参与贡献

请参阅 CONTRIBUTING.md。

许可证

Apache 2.0 — 版权所有 2025–2026 Dunkel Cloud GmbH

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。